智汇工业-智慧工业、智能制造及工业智能、工业互联门户网站,专业的工业“互联网+”传媒

Android游戲開發之詳解SQLite存儲

來源:網絡

點擊:1065

A+ A-

所屬頻道:新聞中心

關鍵詞: Android,游戲開發,SQLite,存儲

      先介紹幾個基本概念知識:

      什么是SQLite:

      SQLite是一款輕量級數據庫,它的設計目的是嵌入式,而且它占用的資源非常少,在嵌入式設備中,只需要幾百KB!!!!!

      SQLite的特性:

      輕量級

      使用 SQLite 只需要帶一個動態庫,就可以享受它的全部功能,而且那個動態庫的尺寸想當小。

      獨立性

      SQLite 數據庫的核心引擎不需要依賴第三方軟件,也不需要所謂的“安裝”。

      隔離性

      SQLite 數據庫中所有的信息(比如表、視圖、觸發器等)都包含在一個文件夾內,方便管理和維護。

      跨平臺

      SQLite 目前支持大部分操作系統,不至電腦操作系統更在眾多的手機系統也是能夠運行,比如:Android。

      多語言接口

      SQLite 數據庫支持多語言編程接口。

      安全性

      SQLite 數據庫通過數據庫級上的獨占性和共享鎖來實現獨立事務處理。這意味著多個進程可以在同一時間從同一數據庫讀取數據,但只能有一個可以寫入數據。

      優點:

            1.能存儲較多的數據。

      2.能將數據庫文件存放到SD卡中!

      什么是 SQLiteDatabase?

      一個 SQLiteDatabase 的實例代表了一個SQLite 的數據庫,通過SQLiteDatabase 實例的一些方法,我們可以執行SQL 語句,對數 據庫進行增、刪、查、改的操作。需要注意的是,數據庫對于一個應用來說是私有的,并且在一個應用當中,數據庫的名字也是惟一的。

      什么是 SQLiteOpenHelper ?

      根據這名字,我們可以看出這個類是一個輔助類。這個類主要生成一個數據庫,并對數據庫的版本進行管理。當在程序當中調用這個類的 方法getWritableDatabase(),或者getReadableDatabase()方法的時候,如果當時沒有數據,那么Android 系統就會自動生成一 個數 據庫。SQLiteOpenHelper 是一個抽象類,我們通常需要繼承它,并且實現里邊的3 個函數,

      什么是 ContentValues 類?

      ContentValues 類和Hashmap/Hashtable 比較類似,它也是負責存儲一些名值對,但是它存儲的名值對當中的名是一個

      String 類型,而值都是基本類型。

      什么是 Cursor ?

      Cursor 在Android 當中是一個非常有用的接口,通過Cursor 我們可以對從數據庫查詢出來的結果集進行隨 機的讀寫訪問。

      OK,基本知識就介紹到這里,下面開始上代碼:還是按照我的一貫風格,代碼中該解釋的地方都已經在代碼中及時注釋和講解了!

      順便來張項目截圖:

      

      先給出xml:

      view plaincopy to clipboardprint?

      ·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

      《?xml version=“1.0” encoding=“utf-8”?》

      《LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

      android:orientation=“vertical” android:layout_width=“fill_parent”

      android:layout_height=“fill_parent”》

      《TextView android:layout_width=“fill_parent”

      android:layout_height=“wrap_content” android:text=“SQL 練習!(如果你使用的SD卡存儲數據方式,為了保證正常操作,請你先點擊創建一張表然后再操作)”

      android:textSize=“20sp” android:textColor=“#ff0000” android:id=“@+id/tv_title” /》

      《Button android:id=“@+id/sql_addOne” android:layout_width=“fill_parent”

      android:layout_height=“wrap_content” android:text=“插入一條記錄”》《/Button》

      《Button android:id=“@+id/sql_check” android:layout_width=“fill_parent”

      android:layout_height=“wrap_content” android:text=“查詢數據庫”》《/Button》

      《Button android:id=“@+id/sql_edit” android:layout_width=“fill_parent”

      android:layout_height=“wrap_content” android:text=“修改一條記錄”》《/Button》

      《Button android:id=“@+id/sql_deleteOne” android:layout_width=“fill_parent”

      android:layout_height=“wrap_content” android:text=“刪除一條記錄”》《/Button》

      《Button android:id=“@+id/sql_deleteTable” android:layout_width=“fill_parent”

      android:layout_height=“wrap_content” android:text=“刪除數據表單”》《/Button》

      《Button android:id=“@+id/sql_newTable” android:layout_width=“fill_parent”

      android:layout_height=“wrap_content” android:text=“新建數據表單”》《/Button》

      《/LinearLayout》

      xml中定義了我們需要練習用到的幾個操作按鈕,這里不多解釋了,下面看java源碼:先看我們繼承的 SQLiteOpenHelper 類

      view plaincopy to clipboardprint?

      ·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

      package com.himi;

      import android.content.Context;

      import android.database.sqlite.SQLiteDatabase;

      import android.database.sqlite.SQLiteOpenHelper;

      import android.util.Log;

      /**

      *

      * @author Himi

      * @解釋 此類我們只需要傳建一個構造函數 以及重寫兩個方法就OK啦、

      *

      */

      public class MySQLiteOpenHelper extends SQLiteOpenHelper {

      public final static int VERSION = 1;// 版本號

      public final static String TABLE_NAME = “himi”;// 表名

      public final static String ID = “id”;// 后面ContentProvider使用

      public final static String TEXT = “text”;

      public static final String DATABASE_NAME = “Himi.db”;

      public MySQLiteOpenHelper(Context context) {

      // 在Android 中創建和打開一個數據庫都可以使用openOrCreateDatabase 方法來實現,

      // 因為它會自動去檢測是否存在這個數據庫,如果存在則打開,不過不存在則創建一個數據庫;

      // 創建成功則返回一個 SQLiteDatabase對象,否則拋出異常FileNotFoundException。

      // 下面是來創建一個名為“DATABASE_NAME”的數據庫,并返回一個SQLiteDatabase對象

      super(context, DATABASE_NAME, null, VERSION);

      }

      @Override

      // 在數據庫第一次生成的時候會調用這個方法,一般我們在這個方法里邊生成數據庫表;

      public void onCreate(SQLiteDatabase db) {

      String str_sql = “CREATE TABLE ” + TABLE_NAME + “(” + ID

      + “ INTEGER PRIMARY KEY AUTOINCREMENT,” + TEXT + “ text );”;

      // CREATE TABLE 創建一張表 然后后面是我們的表名

      // 然后表的列,第一個是id 方便操作數據,int類型

      // PRIMARY KEY 是指主鍵 這是一個int型,用于唯一的標識一行;

      // AUTOINCREMENT 表示數據庫會為每條記錄的key加一,確保記錄的唯一性;

      // 最后我加入一列文本 String類型

      // ----------注意:這里str_sql是sql語句,類似dos命令,要注意空格!

      db.execSQL(str_sql);

      // execSQL()方法是執行一句sql語句

      // 雖然此句我們生成了一張數據庫表和包含該表的sql.himi文件,

      // 但是要注意 不是方法是創建,是傳入的一句str_sql這句sql語句表示創建!!

      }

      @Override

      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

      // 一般默認情況下,當我們插入 數據庫就立即更新

      // 當數據庫需要升級的時候,Android 系統會主動的調用這個方法。

      // 一般我們在這個方法里邊刪除數據表,并建立新的數據表,

      // 當然是否還需要做其他的操作,完全取決于游戲需求。

      Log.v(“Himi”, “onUpgrade”);

      }

      }

      我喜歡代碼中立即附上解釋,感覺這樣代碼比較讓大家更容易理解和尋找,當然如果童鞋們不喜歡,可以告訴我,我改~嘿嘿~

      下面看最重要的MainActivity中的代碼:

      view plaincopy to clipboardprint?

      ·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

      package com.himi;

      import java.io.File;

      import java.io.IOException;

      import android.app.Activity;

      import android.content.ContentValues;

      import android.database.Cursor;

      import android.database.sqlite.SQLiteDatabase;

      import android.os.Bundle;

      import android.view.View;

      import android.view.Window;

      import android.view.WindowManager;

      import android.view.View.OnClickListener;

      import android.widget.Button;

      import android.widget.TextView;

      // ------------第三種保存方式--------《SQLite》---------

      /**

      * @author Himi

      * @保存方式:SQLite 輕量級數據庫、

      * @優點: 可以將自己的數據存儲到文件系統或者數據庫當中, 也可以將自己的數據存

      * 儲到SQLite數據庫當中,還可以存到SD卡中

      * @注意1:數據庫對于一個游戲(一個應用)來說是私有的,并且在一個游戲當中,

      * 數據庫的名字也是唯一的。

      * @注意2 apk中創建的數據庫外部的進程是沒有權限去讀/寫的,

      * 我們需要把數據庫文件創建到sdcard上可以解決類似問題。

      * @注意3 當你刪除id靠前的數據或者全部刪除數據的時候,SQLite不會自動排序,

      * 也就是說再添加數據的時候你不指定id那么SQLite默認還是在原有id最后添加一條新數據

      * @注意4 android 中 的SQLite 語法區分大小寫的!!!!!這點要注意!

      * String UPDATA_DATA = “UPDATE himi SET text=‘通過SQL語句來修改數據’ WHERE id=1”;

      * 千萬 不能可以寫成

      * String UPDATA_DATA = “updata himi set text=‘通過SQL語句來修改數據’ where id=1”;

      */

      public class MainActivity extends Activity implements OnClickListener {

      private Button btn_addOne, btn_deleteone, btn_check, btn_deleteTable,

      btn_edit, btn_newTable;

      private TextView tv;

      private MySQLiteOpenHelper myOpenHelper;// 創建一個繼承SQLiteOpenHelper類實例

      private SQLiteDatabase mysql ;

      //---------------以下兩個成員變量是針對在SD卡中存儲數據庫文件使用

      // private File path = new File(“/sdcard/himi”);// 創建目錄

      // private File f = new File(“/sdcard/himi/himi.db”);// 創建文件

      @Override

      public void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

      getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

      WindowManager.LayoutParams.FLAG_FULLSCREEN);

      this.requestWindowFeature(Window.FEATURE_NO_TITLE);

      setContentView(R.layout.main);

      tv = (TextView) findViewById(R.id.tv_title);

      btn_addOne = (Button) findViewById(R.id.sql_addOne);

      btn_check = (Button) findViewById(R.id.sql_check);

      btn_deleteone = (Button) findViewById(R.id.sql_deleteOne);

      btn_deleteTable = (Button) findViewById(R.id.sql_deleteTable);

      btn_newTable = (Button) findViewById(R.id.sql_newTable);

      btn_edit = (Button) findViewById(R.id.sql_edit);

      btn_edit.setOnClickListener(this);

      btn_addOne.setOnClickListener(this);

      btn_check.setOnClickListener(this);

      btn_deleteone.setOnClickListener(this);

      btn_deleteTable.setOnClickListener(this);

      btn_newTable.setOnClickListener(this);

      myOpenHelper = new MySQLiteOpenHelper(this);// 實例一個數據庫輔助器

      //備注1 ----如果你使用的是將數據庫的文件創建在SD卡中,那么創建數據庫mysql如下操作:

      // if (!path.exists()) {// 目錄存在返回false

      // path.mkdirs();// 創建一個目錄

      // }

      // if (!f.exists()) {// 文件存在返回false

      // try {

      // f.createNewFile();//創建文件

      // } catch (IOException e) {

      // // TODO Auto-generated catch block

      // e.printStackTrace();

      // }

      // }

      }

      @Override

      public void onClick(View v) {

      try {

      //備注2----如果你使用的是將數據庫的文件創建在SD卡中,那么創建數據庫mysql如下操作:

      // mysql = SQLiteDatabase.openOrCreateDatabase(f, null);

      //備注3--- 如果想把數據庫文件默認放在系統中,那么創建數據庫mysql如下操作:

      mysql = myOpenHelper.getWritableDatabase(); // 實例數據庫

      if (v == btn_addOne) {// 添加數據

      // ---------------------- 讀寫句柄來插入---------

      // ContentValues 其實就是一個哈希表HashMap, key值是字段名稱,

      //Value值是字段的值。然后 通過 ContentValues 的 put 方法就可以

      //把數據放到ContentValues中,然后插入到表中去!

      ContentValues cv = new ContentValues();

      cv.put(MySQLiteOpenHelper.TEXT, “測試新的數據”);

      mysql.insert(MySQLiteOpenHelper.TABLE_NAME, null, cv);

      // inser() 第一個參數 標識需要插入操作的表名

      // 第二個參數 :默認傳null即可

      // 第三個是插入的數據

      // ---------------------- SQL語句插入--------------

      // String INSERT_DATA =

      // “INSERT INTO himi (id,text) values (1, ‘通過SQL語句插入’)”;

      // db.execSQL(INSERT_DATA);

      tv.setText(“添加數據成功!點擊查看數據庫查詢”);

      } else if (v == btn_deleteone) {// 刪除數據

      // ---------------------- 讀寫句柄來刪除

      mysql.delete(“himi”, MySQLiteOpenHelper.ID + “=1”, null);

      // 第一個參數 需要操作的表名

      // 第二個參數為 id+操作的下標 如果這里我們傳入null,表示全部刪除

      // 第三個參數默認傳null即可

      // ----------------------- SQL語句來刪除

      // String DELETE_DATA = “DELETE FROM himi WHERE id=1”;

      // db.execSQL(DELETE_DATA);

      tv.setText(“刪除數據成功!點擊查看數據庫查詢”);

      } else if (v == btn_check) {// 遍歷數據

      //備注4------

      Cursor cur = mysql.rawQuery(“SELECT * FROM ”

      + MySQLiteOpenHelper.TABLE_NAME, null);

      if (cur != null) {

      String temp = “”;

      int i = 0;

      while (cur.moveToNext()) {//直到返回false說明表中到了數據末尾

      temp += cur.getString(0);

      // 參數0 指的是列的下標,這里的0指的是id列

      temp += cur.getString(1);

      // 這里的0相對于當前應該是咱們的text列了

      i++;

      temp += “ ”; // 這里是我整理顯示格式 ,呵呵~

      if (i % 3 == 0) // 這里是我整理顯示格式 ,呵呵~

      temp += “\n”;// 這里是我整理顯示格式 ,呵呵~

      }

      tv.setText(temp);

      }

      } else if (v == btn_edit) {// 修改數據

      // ------------------------句柄方式來修改 -------------

      ContentValues cv = new ContentValues();

      cv.put(MySQLiteOpenHelper.TEXT, “修改后的數據”);

      mysql.update(“himi”, cv, “id ” + “=” + Integer.toString(3), null);

      // ------------------------SQL語句來修改 -------------

      // String UPDATA_DATA =

      // “UPDATE himi SET text=‘通過SQL語句來修改數據’ WHERE id=1”;

      // db.execSQL(UPDATA_DATA);

      tv.setText(“修改數據成功!點擊查看數據庫查詢”);

      } else if (v == btn_deleteTable) {// 刪除表

      mysql.execSQL(“DROP TABLE himi”);

      tv.setText(“刪除表成功!點擊查看數據庫查詢”);

      } else if (v == btn_newTable) {// 新建表

      String TABLE_NAME = “himi”;

      String ID = “id”;

      String TEXT = “text”;

      String str_sql2 = “CREATE TABLE ” + TABLE_NAME + “(” + ID

      + “ INTEGER PRIMARY KEY AUTOINCREMENT,” + TEXT

      + “ text );”;

      mysql.execSQL(str_sql2);

      tv.setText(“新建表成功!點擊查看數據庫查詢”);

      }

      // 刪除數據庫:

      // this.deleteDatabase(“himi.db”);

      } catch (Exception e) {

      tv.setText(“操作失敗!”);

      } finally {// 如果try中異常,也要對數據庫進行關閉

      mysql.close();

      }

      }

      }

      以上代碼中我們實現了兩種存儲方式:

      一種存儲默認系統路徑/data-data-com.himi-databases下,另外一種則是保存在了/sdcard-himi下,生成數據庫文件himi.db

      那么這里兩種實現方式大概步驟和區別說下:

      -----------如果我們使用默認系統路徑存儲數據庫文件:

      第一步:新建一個類繼承SQLiteOpenHelper;寫一個構造,重寫兩個函數!

      第二步:在新建的類中的onCreate(SQLiteDatabase db) 方法中創建一個表;

      第三步:在進行刪除數據、添加數據等操作的之前我們要得到數據庫讀寫句柄得到一個數據庫實例;

      注意: 繼承寫這個輔助類,是為了在我們沒有數據庫的時候自動為我們生成一個數據庫,并且生成數據庫文件,這里也同時創建了一張表,因為我們在onCreate里是在數據庫中創建一張表的操作;這里還要注意在我們new 這個我們這個MySQLiteOpenHelper 類實例對象的時候并沒有創建數據庫喲~!而是在我們調用 (備注3)MySQLiteOpenHelper 。.getWritableDatabase() 這個方法得到數據庫讀寫句柄的時候,android 會分析是否已經有了數據庫,如果沒有會默認為我們創建一個數據庫并且在系統路徑data-data-com.himi-databases下生成himi.db 文件!

      (如果我們使用sd卡存儲數據庫文件,就沒有必要寫這個類了,而是我們自己Open自己的文件得到一個數據庫,西西,反而方便~ )

      -----------如果我們需要把數據庫文件存儲到SD卡中:

      第一步:確認模擬器存在SD卡,關于SD卡的兩種創建方法見我的博文:【Android 2D游戲開發之十】

      第二步:(備注1)先創建SD卡目錄和路徑已經我們的數據庫文件!這里不像上面默認路徑中的那樣,如果沒有數據庫會默認系統路徑生成一個數據庫和一個數據庫文件!我們必須手動創建數據庫文件!

      第三步:在進行刪除數據、添加數據等操作的之前我們要得到數據庫讀寫句柄得到一個數據庫實例;(備注2)此時的創建也不是像系統默認創建,而是我們通過打開第一步創建好的文件得到數據庫實例。這里僅僅是創建一個數據庫!!!!

      第四步:在進行刪除數據、添加數據等操作的之前我們還要創建一個表!

      第五步:在配置文件AndroidMainfest.xml 聲明寫入SD卡的權限,上一篇已經介紹權限了,不知道的自己去看下吧。

      有些童鞋不理解什么默認路徑方式中就有表?那是因為我們在它默認給我們創建數據庫的時候我們有創建表的操作,就是MySQLiteOpenHelper類中的onCreate()方法里的操作!所以我們如果要在進行刪除數據、添加數據等操作的之前還要創建一個表,創建表的方法都是一樣的。

      總結:不管哪種方式我們都要-創建數據庫-創建表-然后進行操作!

      備注4:

      在Android中查詢數據是通過Cursor類來實現的,當我們使用SQLiteDatabase.query()方法時,會得到一個Cursor對象,Cursor指向的就是每一條數據。它提供了很多有關查詢的方法,具體方法如下:

      以下是方法和說明:

      move 以當前的位置為參考,將Cursor移動到指定的位置,成功返回true, 失敗返回false

      moveToPosition 將Cursor移動到指定的位置,成功返回true,失敗返回false

      moveToNext 將Cursor向前移動一個位置,成功返回true,失敗返回false

      moveToLast 將Cursor向后移動一個位置,成功返回true,失敗返回 false。

      movetoFirst 將Cursor移動到第一行,成功返回true,失敗返回false

      isBeforeFirst 返回Cursor是否指向第一項數據之前

      isAfterLast 返回Cursor是否指向最后一項數據之后

      isClosed 返回Cursor是否關閉

      isFirst 返回Cursor是否指向第一項數據

      isLast 返回Cursor是否指向最后一項數據

      isNull 返回指定位置的值是否為null

      getCount 返回總的數據項數

      getInt 返回當前行中指定的索引數據

      對于SQLite的很多童鞋有接觸過,但是就不知道怎么存儲在SD中,所以我也研究了下,這篇也寫了把sd卡中的方式也提供給大家。

    (審核編輯: 智匯小新)

    聲明:除特別說明之外,新聞內容及圖片均來自網絡及各大主流媒體。版權歸原作者所有。如認為內容侵權,請聯系我們刪除。

    主站蜘蛛池模板: 耐磨工业软管,PTFE耐腐蚀软管,耐磨喷砂胶管,超耐磨软管厂家,漯河利通液压管利通科技-耐磨工业软管,PTFE耐腐蚀软管,耐磨喷砂胶管,超耐磨软管厂家,漯河利通液压管利通科技 | 铸铁平台-铸铁平板平台厂家-加工优质高精度检验划线装配T型槽平台-尺寸规格全供应-建新铸造 | 铝合金锻造|链轮曲柄-同力铝业股份有限公司 | 三叶罗茨鼓风机_三叶罗茨风机厂家_山东九洲四海机械有限公司 | 石笼网|镀锌石笼网|石笼网价格|包胶涂塑石笼网箱-河北海峰石笼网厂 | 烟台天昊矿业有限公司、滑石、滑石粉、微细粉、滑石矿-烟台天昊矿业有限公司 | 天力普电力科技有限公司 | 全开式真空干燥机_全开耙式真空干燥机_全开式动态真空干燥机,江阴千峰机械制造有限公司 | 意大利留学-意大利语培训-马来西亚留学【长青藤海外】 | 消防施工,消防工程施工,消防施工改造-北京消防工程公司-亿杰(北京)消防工程有限公司 | 微机继电保护测试仪,单相继电保护测试仪,三相继电保护测试仪,六相继电保护测试仪,介质损耗测试仪,氧化锌避雷器测试仪,无线核相仪-扬州豪泰电力科技有限公司 | 转炉烟道,转炉汽化冷却烟道,转炉汽化烟道,汽化冷却烟道系统生产厂家-宏发制造集团有限公司原河北宏发机械有限公司 | 压力变送器,差压变送器,液位变送器,温度变送器生产厂家价格-西安仕乐克仪表科技有限公司 | 慢直播摄像头厂家,监控直播摄像机厂家,景区慢直播设备,rtmp推流直播摄像头,实时摄像头监控直播-监控慢直播厂家:专注监控慢直播系统解决方案 | 树枝粉碎机,锯末机,木材粉碎机的专业生产厂家利鑫机械,问价格找利鑫 | 铸铁平台-铸铁平板平台厂家-加工优质高精度检验划线装配T型槽平台-尺寸规格全供应-建新铸造 | 上海网站建设-上海网站制作-网站设计-上海做网站公司-SEO优化推广-咏熠软件 | 上海先顶仪器设备有限公司-国产氮气发生器-进口氮气发生器 | 线束加工_线束加工厂_线束厂-苏州缆仕特电子有限公司 | 三禾防爆-专业的防爆电气生产厂家| 金属探测机_食品金属探测仪_食品金属探测器_广东善安金属检测机 金属剪切机,金属打包机,废钢剪切机,废铁压块机,金属压块机,废纸打包机,重废龙门剪,废钢龙门剪,箱式剪,液压剪切机-瑞顿机械装备制造江阴有限公司 | 菏泽代理公司|菏泽代办公司|菏泽公司注册|公司变更注销 | 频谱矢量网络分析仪_鼎阳数字示波器-苏州东伟元电子有限公司 | 无锡亮鑫不锈钢有限公司-不锈钢炉胆,马弗炉胆,耐高温炉胆,310s炉胆,网带炉 | 太原仪诚实验室设备有限公司| 网带式等温正火生产线_燃气式铝合金加热炉_燃气式烘干窑炉-湖州中科炉业科技有限公司 | 斜管填料_斜板填料_纤维球_果壳活性炭_立体网状填料_纤维球厂家-巩义市德科净水材料有限公司 | 河北湛存边坡防护工程有限公司-边坡防护网_边坡绿化修复_喷浆挂网 | 金煌家装官网-长沙装饰|长沙装修|长沙装修公司|长沙装饰公司-金煌家装 | 上海办公家具_高端实木办公家具_现代智能办公家具定制厂-上海迈亚家具有限公司 | 新房_二手房_别墅_全包装修-天美艺装饰【官网】-深圳装修公司 | 山东发电机组生产厂家,特种火花塞生产厂家,高压线生产厂家,空气滤芯生产厂家,济南市博盛动力机械有限公司 | 品牌策划-品牌设计-济南之式传媒广告有限公司官网-提供品牌整合丨影视创意丨公关活动丨数字营销丨自媒体运营丨数字营销 | 河北热风机,电热暖风机,燃油暖风机,工业暖风机厂家安装,批发-河北嘉鹏冷暖风机有限公司 | 移动破碎站-洗沙机-球磨制砂机-污泥处理-青州冠诚重工机械有限公司 | 威学一百-专注国际学校择校备考-DSE-A-level-雅思-托福-OSSD-港澳台联考-AP-IGCSE-IB-AMC-多邻国-PTE-SAT-SSAT-小语种(如日语,韩语,德语,法语,西班牙语,意大利语,俄语,泰语)等考试培训,为出国留学学生提供个性化定制性学习方案,线下实体面授+线上网络课程, 提供一对一,小班课等多种班型 | 深圳理津技术有限公司(REHLOGY)-全球工业品供应商:自动化产品|仪器仪表|设备|备品备件|工具|消耗品|非标设备|建筑工程等一站式综合服务! | 拓普思(常州)智能科技有限公司-青少年无人机教育培训比赛课程加盟拓活力 | 呼吸家官网|肺功能检测仪生产厂家|国产肺功能仪知名品牌|肺功能检测仪|肺功能测试仪|婴幼儿肺功能仪|弥散残气肺功能仪|肺功能测试系统|广州红象医疗科技有限公司|便携式肺功能仪|大肺功能仪|呼吸康复一体机|儿童肺功能仪|肺活量计|医用简易肺功能仪|呼吸康复系统|肺功能仪|弥散肺功能仪(大肺)|便携式肺功能检测仪|肺康复|呼吸肌力测定肺功能仪|肺功能测定仪|呼吸神经肌肉刺激仪|便携式肺功能 | 箱式电炉,箱式烧结炉,箱式马弗炉,箱式实验炉,高温箱式电阻炉,箱式加热炉,箱式退火炉,箱式真空气氛炉洛阳研博炉业有限公司 | 石墨热场|PECVD石墨舟|碳碳框|燃料电池双极板|半导体石墨|光纤用石墨模具|石墨电极加工|石墨制品|上海弘竣新能源材料有限公司 |