這個例子是App應用程式中對資料存取很常見之技巧,要融會貫通在日後開發相類似時可用,通常與資料庫扯上關係是要通過CursorAdapter作為中間媒介,其它相關之Adapter類型都無法達到此要求(因資料存取作業須有指標配合方能運作),至於資料呈現本例採用最常見之ListView來顯示。
主類之代碼如下:
public class DbaccessActivity extends ListActivity{
//建立Gloabal變數
    private SQLiteDatabase  db = null;
    private Cursor cursor = null;    
    private SimpleCursorAdapter adapter = null;

    protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
//取用可寫入型資料庫
        db= (new
Dbcls (getApplicationContext())).getWritableDatabase();    // Dbcls為繼承SQLiteOpenHelper抽象類別之子類
//輸入SQL Commnad指令取用資料(RAW 方式)
cursor =db.rawQuery("SELECT _id,Name,Weight from mytable ORDER BY Weight", null);


 //layout/access.xml定義了ListViewItem之佈局,其Item使用元件之idR.id.nameR.id.gravity均為TextView,分列左右
 //建立CursorAdapter
  adapter = new SimpleCursorAdapter(this, R.layout.access, cursor,  new String[]{"Name","Weight"}, new int[]{R.id.name, R.id.gravity});
//前為指定指標資料的名稱(含類型定義),實際為Table欄位名稱,後為,對應的UI控件的id
  //CursorAdapter設入ListAdapter(因本例extends ListActivity)
    setListAdapter(adapter);
 }

    protected void onDestroy() {
        super.onDestroy();
    
    cursor.close();    //釋放Cursor資源
        db.close();      //關閉資料庫的連接以釋放相關資源
    }
}
運行一下程式展示結果如下:
Ø   資料異動作業(本例以加入資料為例作說明應用,至於刪除資料則採用ContextMenu方式進行)
通過Menu彈出功能表,按「Add」按鈕以彈出一個Dialog,可在此當中填入相關資料,之後使其在SQLite資料庫mytable表格中加入所填之資料,並且同步ListView的畫面顯示。茲將需求之作法列述如下:
1.       建立OptionsMenu功能表物件,並在其內設置「Add」按鍵,當按下時觸發執行add()方法。
2.       add()方法中彈出指定之AlertDialog(格式在xml中定義)以進行 加入資料處理作業,具體代碼如下:
private void add(){
   
 //步驟2.1:通過LayoutInflaterXML檔中生成View
    LayoutInflater inflater = LayoutInflater.from(this);
    final View addView = inflater.inflate(R.layout.add_dialgo,null);

    //步驟2.2:通過AlertDialog彈出對話方塊,並且在第一個button,即PositiveButton設定監聽事件
    new AlertDialog.Builder(this)
    .setTitle("添加框")
    .setView(addView)
    .setPositiveButton("確定", new DialogInterface.OnClickListener() {
        //因希望由addView中得到資料,但這個inner class只能獲取final的值,所以須將addView設置為final,也就是所有addView的位址是固定的,而不是動態生成。
        public void onClick(DialogInterface dialog, int which) {
      
 //取得UI介面之控件
            EditText nameView = (EditText)addView.findViewById(R.id.name);
            EditText weigthView = (EditText)addView.findViewById(R.id.weight);
      
            // addData是下面步驟3之自訂方法,實現SQLite的資料更新和ListView的顯示同步add(name,weight)方法;
            addData(nameView.getText().toString(), new Float(weigthView.getText().toString()).floatValue());
        }
    })
    .setNegativeButton("取消",null)
    .show();
}
3.       實現更新資料庫和同步ListView之顯示,具體代碼如下:
  private void addData(String name ,float weight){
 
       /* 略去資料的判斷,例如如果name一樣,採用update的方式等等*/
        //
步驟3.1 在資料庫表格中添加資料
        ContentValues values = new ContentValues(
2);   //指定具2個值域
        values.put("Name",name);
        values.put("Weight",weight);
        db.insert("mytable","Name",values);

    

    
    //步驟3.2 同步ListView(更新指標的資訊)
        cursor.requery();
    }
Ø   以後臺非同步執行緒進行資料更新與同步顯示
前述例子是採用Cursorrequery()方法來進行資料重整作業,此在資料較少的時候,仍可安全地使用,但是對於具有大量資料時則會有很大風險的存在,其因資料量大會導致重寫讀取事件會進行很長之執行時間,造成使用者體驗感受不佳。其修訂的方式是採用非同步(AsyncTask)技術來改進,思路如下:
1.       通過後臺之執行緒來讀取資料庫;
2.       通過更換新的cursor來更新ListView,具體代碼如下:
//步驟1:通過後臺執行緒AsyncTask來讀取資料庫,放入一個更換新的指標Cursor
private class RefreshList extends AsyncTask {      //※此為新技術AsyncTask執行緒之概念
  
  //步驟1.1:在後臺執行緒中進行資料庫讀取,並返回新的指標newCursor 
    protected Cursor doInBackground(Void... params) { 
        Cursor newCursor =  db.rawQuery("SELECT _id,Name,Weight from mytable ORDER BY Weight", null); 
        return newCursor; 
    }

  
  //步驟1.2:執行緒之最後執行步驟,更換adapter的指標,並關閉指標及資料庫以釋放資源  
    protected void onPostExecute(Cursor newCursor) { 
        adapter. changeCursor( newCursor);
  //更新ListView採用之Adapter(※以新的cursor作更換)
     

        cursor.close(); 
        cursor = newCursor; 
    }         
} 
//步驟2:取消requrey方式,改採用後臺AsyncTask執行緒進行更新作業 
private void addData(String name ,float weight){ 
      ... ... 
    
//cursor.requery(); 
    new RefreshList().execute(); 
}

Ø   通過ContextMenu來刪除ListView資料
ContextMenu為使用者手指長按某個View時觸發顯示之功能表,換言之,即當使用者長按ListView中之某個Item元素,則使之彈出ContextMenu功能表,此時選按「Delete」按鈕則會彈出另一個AlertDialog訊息框,請用戶確認是否進行刪除,當確定後將資料從SQLite中刪除,且同步更新ListView之顯示,具體代碼如下:
 protected void onCreate(Bundle savedInstanceState) { 
        ... ... 
//如前
 
       //步驟1:向ListView註冊Context Menu,當系統檢測到使用者長按某元素時觸發Context Menu
        registerForContextMenu(getListView()); 
    } 

    // 步驟2:創建ContextMenu(OptionMenu),當使用者長按元素後彈出功能表 
    public void onCreateContextMenu(ContextMenu menu, View v,  ContextMenuInfo menuInfo) { 
        menu.add(Menu.NONE,DELETE_ID,Menu.NONE,"Delete"); 
        super.onCreateContextMenu(menu, v, menuInfo); 
    } 

    //步驟 3: 定義ContextMenu的觸發事件,本例以觸發delete()作舉例說明
    public boolean onContextItemSelected(MenuItem item) { 
        switch(item.getItemId()){ 
        case DELETE_ID: 
/* 在此處,我們關鍵引入 AdapterView.AdapterContextMenuInfo來獲取單元的資訊,其參數含有三個重要的資訊,如下:
     1
idThe row id of the item for which the context menu is being displayed ,在cursorAdapter中,實際指的就是表格的_id序號;
     2
position:為list中元素的順序位置;
     3
view:為list中點擊元素的View,透過view可以獲取裡面的顯示的資訊   */ 
            AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); 
            delete(info.id); 
            return true;
        default:
            break; 
        } 
         return super.onContextItemSelected(item); 
    } 

    //步驟4: 對觸發彈出功能框(Add的相似),當確定後即進行更新資料庫和同步ListView的顯示,其中getNameById是通過id查名字的方法。值得注意的是,為了內部類中使用,delete的參數採用final的形式 
    p
rivate void delete(final long  rowId){ 
        if(rowId>0){ 
            new AlertDialog.Builder(this) 
            .setTitle("刪除" + getNameById(rowId))
            .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                      deleteData(rowId);
                }
            })
            .setNegativeButton("取消", null)
            .show(); 
        } 
    } 
     
    private void deleteData(long rowId){ 
        String[] str = {String.valueOf(rowId)};
        db.delete("mytable","_id=?",str); 
        new RefreshList().execute();    //採用後臺方式,當然也可以用crusor.requery()來處理 
    } 
運行程式顯示效果如下:
Ø   通過模擬器的Console進行資料庫操作
android-sdk-windows/platform-tools目錄下有個adb命令,於命令模式下輸入adb shell,可提供模擬器的console視窗。資料庫檔存放的位置為/data/data/your.app.package/databases/your-db-name,進入資料庫指定目錄後,可使用#sqlite3 your-db-name即可進入資料庫,在此即可執行SQL語句進行資料處理操作,如通過#.schema來查看表格的格式,通過#select * from mytable;可以顯示資料庫的內容。