Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android入門筆記 - 數據存儲 - SQLite,單元測試

Android入門筆記 - 數據存儲 - SQLite,單元測試

編輯:關於Android編程

今天我們來接觸一個輕輕輕量級數據庫(SQLite),為什麼要加3個輕呢?因為它確實很輕大笑。 Sqlite是專門未嵌入式設備准備的輕量級數據庫,麻雀雖小,五髒俱全,sqlite的功能卻一點都不少。它和其他的數據庫:MySql,SqlServer,Oracle等數據庫的最大區別我覺得就是Sqlite只能運行在終端,不能用在服務器上,這也體現了它為嵌入式設備工作的初衷。

好了,來看看今天的內容:

SQLiteAndroid單元測試

今天我們不僅要介紹sqlite,還要簡單介紹一下怎麼使用android的單元測試。如果不知道什麼是單元測試,那就去找google吧!


在android中使用 sqlite數據庫,一般要通過一個協助類: SQLiteOpenHelper,這個類中有兩個方法:onCreate() ,和 onUpgrade()。

onCreate() 在數據庫第一次被創建時才調用。onUpgrade()當數據庫版本更新時調用。

是什麼意思呢?來看看代碼:

package db;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.transition.Transition;
import android.util.Log;

public class DBOpenHelper extends SQLiteOpenHelper {
	private static final String TAG = "DBOpenHelper";
	private Context mContext;
	private String mDBname;
	private String mTableName = "students";
	private SQLiteDatabase mDatabase;
	private int mVersion;

	private String CREATE_TABLE = "create table if not exists " + mTableName
			+ " (_id integer primary key, name text)";

	public DBOpenHelper(Context context, String dbname, CursorFactory factory,
			int version) {
		super(context, dbname, factory, version);
		this.mContext = context;
		this.mDBname = dbname;
		this.mVersion = version;
	}
	
	@Override
	public void onCreate(SQLiteDatabase db) {
		Log.e(TAG, "onCreate");
		db.execSQL(CREATE_TABLE);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		Log.e(TAG, "onUpgrade");
	}

	public long insert(String data) {
		if (mDatabase == null) {
			mDatabase = getWritableDatabase();
		}
		ContentValues values = new ContentValues();
		values.put("name", data);
		return mDatabase.insert(mTableName, "_id", values);
	}

	public int delete(int id) {
		if (mDatabase == null) {
			mDatabase = getWritableDatabase();
		}
		return mDatabase.delete(mTableName, "_id" + "=" + id, null);
	}

	public int update(int id, String data) {
		if (mDatabase == null) {
			mDatabase = getWritableDatabase();
		}
		ContentValues values = new ContentValues();
		values.put("name", data);
		return mDatabase.update(mTableName, values, "_id" + "=" + id, null);
	}

	public Cursor getItemAt(int id) {
		if (mDatabase == null) {
			mDatabase = getWritableDatabase();
		}
		Cursor cursor = mDatabase.query(mTableName, new String[] { "_id",
				"name" }, "_id" + "=" + id, null, null, null, null, null);
		if (cursor != null) {
			cursor.moveToFirst();
		}
		return cursor;
	}

	public Cursor getAll() {
		if (mDatabase == null) {
			mDatabase = getWritableDatabase();
		}
		Cursor cursor = mDatabase.query(mTableName, new String[] { "_id",
				"name" }, null, null, null, null, null);
		return cursor;
	}
}
在使用SqliteOpenHelper時,這三個方法是必須的:

	public DBOpenHelper(Context context, String dbname, CursorFactory factory,
			int version) {
		super(context, dbname, factory, version);
		this.mContext = context;
		this.mDBname = dbname;
		this.mVersion = version;
	}
	
	@Override
	public void onCreate(SQLiteDatabase db) {
		Log.e(TAG, "onCreate");
		db.execSQL(CREATE_TABLE);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		Log.e(TAG, "onUpgrade");
	}
構造方法完成 Context, 數據庫名稱,數據庫版本 的初始化,CursorFactory一般用不到,直接穿為null。

在onCreate()我們調用 db.execSQl( CREATE_TABLE) ; 初始化了一張表 “students”,那麼這個DBOpenHelper類也就是為這張表工作了。

至於 onUpdrade()是在調用 構造函數時,version的值 大於 上一個值的時候就會被觸發,然後 onUpgrade()中主要做表的數據修改列啊,備份數據等工作,這裡不講。

然後我們來看看數據庫的增刪改查是怎麼完成的:


增:

使用android提供的ContentValues 可以輕易的初始化要添加的對象,它相當於一個鍵值對,如果有多項,依次用put方法添加就可以了,注意key一定要與數據庫中的列對應。

這裡的 mDatabase 是一個SqliteDatabase 對象,專門用來操作數據庫的,可通過 SqliteOpenHelper. getWritableDatabase()獲得,然後通過調用 insert()方法就可以插入數據。這裡大家需要注意,使用sqlite時,表中必須有一個字段叫 “_id",而且是主鍵自增長,這就是insert的第二個參數的值。

相當於執行 sql語句:

insert into students(_id, name) values(id, name);

	public long insert(String data) {
		if (mDatabase == null) {
			mDatabase = getWritableDatabase();
		}
		ContentValues values = new ContentValues();
		values.put("name", data);
		return mDatabase.insert(mTableName, "_id", values);
	}


刪:

第二個參數是字符串,相當於: "where _id=id " 只是 delete方法自己做了拼接。

相當於執行 sql語句:

delete from students where _id=id;

	public int delete(int id) {
		if (mDatabase == null) {
			mDatabase = getWritableDatabase();
		}
		return mDatabase.delete(mTableName, "_id" + "=" + id, null);
	}


改:

update方法就需要提供 條件, 以及修改的值,對應於 values 和 ”_id"=id 兩個參數。

相當於執行 sql語句:

update students where _id=id set name = "data";

	public int update(int id, String data) {
		if (mDatabase == null) {
			mDatabase = getWritableDatabase();
		}
		ContentValues values = new ContentValues();
		values.put("name", data);
		return mDatabase.update(mTableName, values, "_id" + "=" + id, null);
	}

查:

查找需要注意的是android中使用到了游標作為結果集(java中的ResultSet),如果找到,返回到游標在第一行數據的前面,所以需要先調用一次 cursor.moveToFirst() 或者 cursor.moveToNext() ,這樣就可以指向第一行數據。

	public Cursor getItemAt(int id) {
		if (mDatabase == null) {
			mDatabase = getWritableDatabase();
		}
		Cursor cursor = mDatabase.query(mTableName, new String[] { "_id",
				"name" }, "_id" + "=" + id, null, null, null, null, null);
		if (cursor != null) {
			cursor.moveToFirst();
		}
		return cursor;
	}

	public Cursor getAll() {
		if (mDatabase == null) {
			mDatabase = getWritableDatabase();
		}
		Cursor cursor = mDatabase.query(mTableName, new String[] { "_id",
				"name" }, null, null, null, null, null);
		return cursor;
	}

好了,sqlite的操作看完了,我們來看看怎麼使用 DBOpenHelper這個類。這個時候我們使用到了Android的單元測試。

Android單元測試的配置方法:

1. 在AndroidMainefest.xml 文件中添加注冊。

標簽之間添加: 

根標簽下添加: android:name="android.test.InstrumentationTestRunner"> (注意加粗的部分填寫程序第一個Activity啟動的所在包名)

2. 測試類必須繼承與 AndroidTestCase。

3. 每個測試方法都以 test+要測試的方法 名作為測試方法名, 並且需要拋出異常。

我們來看看代碼:

package Test;

import db.DBOpenHelper;
import android.database.Cursor;
import android.test.AndroidTestCase;
import android.util.Log;

public class TestDBOpenHelper extends AndroidTestCase {
	private static final String TAG = "TestDBOpenHelper";
	
	public void TestInsert() throws Throwable{
		Log.e(TAG,"TestInsert");
		DBOpenHelper dbopenhelper = new DBOpenHelper(mContext, "stu.db", null, 1);
		dbopenhelper.insert("stu1");
		dbopenhelper.insert("stu2");
		dbopenhelper.insert("stu3");
		dbopenhelper.insert("stu4");
		dbopenhelper.insert("stu5");
	}
	
	public void TestDelete(){
		DBOpenHelper dbopenhelper = new DBOpenHelper(mContext, "stu.db", null, 1);
		dbopenhelper.delete(1);
		dbopenhelper.delete(2);
	}
	
	public void TestUpdate(){
		DBOpenHelper dbopenhelper = new DBOpenHelper(mContext, "stu.db", null, 1);
		dbopenhelper.update(3, "333");
		dbopenhelper.update(4, "444");
	}
	
	public void TestGetItemAtId(){
		Log.e(TAG,"TestGetItemAtId");
		DBOpenHelper dbopenhelper = new DBOpenHelper(mContext, "stu.db", null, 1);
		Cursor cursor = dbopenhelper.getItemAt(3);
		Log.e(TAG,"_id="+cursor.getInt(0));
		Log.e(TAG,"name="+cursor.getString(1));
	}
	
	public void TestGetAll(){
		Log.e(TAG,"TestGetAll");
		DBOpenHelper dbopenhelper = new DBOpenHelper(mContext, "stu.db", null, 1);
		Cursor cursor = dbopenhelper.getAll();
		while(cursor.moveToNext()){
			Log.e(TAG,"_id="+cursor.getInt(0));
			Log.e(TAG,"name="+cursor.getString(1));
		}
	}
}

寫好之後我們就可以啟動單元測試來測試我們寫的代碼:

\


如果正確就會綠條,有異常會顯示紅條:

\


單元測試的好處多多,關心代碼質量的同志們都應該學會怎麼使用單元測試,它是為了驗證每個代碼塊都能工作正常而產生的。

測試代碼應該很容易就看懂了:

這是在測試添加數據,只需要new一個 helper對象,然後調用insert方法就可以了,是不是很簡單:

測試插入:

	public void TestInsert() throws Throwable{
		Log.e(TAG,"TestInsert");
		DBOpenHelper dbopenhelper = new DBOpenHelper(mContext, "stu.db", null, 1);
		dbopenhelper.insert("stu1");
		dbopenhelper.insert("stu2");
		dbopenhelper.insert("stu3");
		dbopenhelper.insert("stu4");
		dbopenhelper.insert("stu5");
	}

測試刪除:

	public void TestDelete(){
		DBOpenHelper dbopenhelper = new DBOpenHelper(mContext, "stu.db", null, 1);
		dbopenhelper.delete(1);
		dbopenhelper.delete(2);
	}

測試查找:

	public void TestGetAll(){
		Log.e(TAG,"TestGetAll");
		DBOpenHelper dbopenhelper = new DBOpenHelper(mContext, "stu.db", null, 1);
		Cursor cursor = dbopenhelper.getAll();
		while(cursor.moveToNext()){
			Log.e(TAG,"_id="+cursor.getInt(0));
			Log.e(TAG,"name="+cursor.getString(1));
		}
	}
剛剛我們看到,getAll() 函數返回到是一個 cursor,我們可以通過循環遍歷每個cursor中的對象。 得到cursor某一列的值 可通過 cursor.getXXX( index ) 來獲取,index是column的編號,從0開始,當然也可以通過列的名字來得到。總的來說 Cursor的一行就像一個Map一樣,存放數據庫中的一行數據的鍵值對。


好了,終於完了,最後還是要說一下,上面的例子是很不規范的,當然只是為了體現應該怎麼來使用Sqlite存取數據,在真實的開發中,我們傳入的內容應該是 一個對象,這裡需要和JavaBean結合,就是說數據庫中存儲的數據,其實是針對一個Class的屬性值來存儲的,而不是單個的值。數據庫中的每一行存儲一個對象的所有屬性,當然也可能是幾張表聯合。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved