閱讀485 返回首頁    go 阿裏雲 go 技術社區[雲棲]


通過CursorAdapter在ListView中的數據呈現

在Android中可以通過CursorAdapter直接將數據映射到ListView中,如下處理:

Android中的SQLite、ListView、ContextMenu使用學習public class Chapter22Test1 extends ListActivity{
    private SQLiteDatabase  db = null;
    private Cursor cursor = null;    

    private SimpleCursorAdapter adapter = null;

    protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
        db= (new Chapter22Db (getApplicationContext())).getWritableDatabase();    
        cursor =db.rawQuery("SELECT _id,Name,Weight from mytable ORDER BY Weight", null);
        //layout/chapter_22_test1.xml的Android XML文件定義了ListView中每個單元的排列方式,每個單元R.id.c22_name和R.id.c22_gravity都是TextView,分列左右
        adapter = new SimpleCursorAdapter(this,
                R.layout.chapter_22_test1, 
                cursor, 
                new String[]{"Name","Weight"},//遊標數據的名稱,實際是Table列名字
                new int[]{R.id.c22_name, R.id.c22_gravity});//對應的UI微件的id
        setListAdapter(adapter);
    }

    protected void onDestroy() {
        super.onDestroy();
        cursor.close();  //我們在onCreate()中沒有關閉遊標,因為需要和ListView進行數據關聯,關閉curosr,會導致List無數據,故在最後釋放資源
        db.close(); //斷開和數據庫的連接,釋放相關資源
    }
}

更新數據(以增加為例)

我們要實現:通過Menu彈出菜單,有一個為增加,按之,彈出一個Dialog,可以在當中填入數據,按Dialog的確定按鍵,在SQLite數據庫的表格mytable中加入相關的數據,並且同步ListView的顯示。

第一步:建立OptionsMenu,裏麵有菜單“Add”,按鍵後,觸發執行add()的操作。

第二步:在add()中,要完成彈出指定格式的 Dialog,采用AlertDialog的方式,Dialog的格式在xml中給出。處理方式之前都學過,但是沒有合並使用的例子,包括Dialog的 格式,同ListView中自定義元素的格式一樣,采用LayoutInflater。具體如下:

Android中的SQLite、ListView、ContextMenu使用學習private void add(){
    //步驟2.1:通過LayoutInflater從Android的XML文件中生成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) {
            EditText nameView = (EditText)addView.findViewById(R.id.c22_name);
            EditText weigthView = (EditText)addView.findViewById(R.id.c22_weight);

            // addData是下麵步驟三,實現SQLite的數據更新和ListView的顯示同步add(name,weight);
            addData(nameView.getText().toString(), new Float(weigthView.getText().toString()).floatValue());
        }
    })
    .setNegativeButton("取消",null)
    .show();
}

第三步:更新數據庫和同步ListView,具體如下:

Android中的SQLite、ListView、ContextMenu使用學習    private void addData(String name ,float weight){
        /* 略去數據的判斷,例如如果name一樣,采用update的方式等等*/
        //步驟3.1 在數據庫表格中添加數據

        ContentValues values = new ContentValues(2);
        values.put("Name",name);
        values.put("Weight",weight);
        db.insert("mytable","Name",values);
        //步驟3.2 同步ListView,更新遊標的信息
        cursor.requery();
    }

異步後台同步數據

在上麵的例子,貌似可以,而且的確是可以,但是在Android的API文檔中,Cursor的方法requery()這樣寫道:This method is deprecated.Don't use this. Just request a new cursor, so you can do this asynchronously and update your list view once the new cursor comes back. 這提示我們風險的存在,如果數據量大,會導致重寫讀取的事件長(也就是requery()的執行時間)。雖然手機是人手操作,互動頻率較低,在數據庫數據 少的時候,例如上麵的例子,我們仍然可以安全地使用requery。但是對於具有大量數據時,我們就需要修改上麵的程序。

修訂的方式步驟如下:1,通過後台線程來讀取數據庫;2、通過更換cursor來更新ListView,具體如下:

//步驟1:通過後台線程AsyncTask來讀取數據庫,放入更換Cursor
private class RefreshList extends 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. changeCursornewCursor); //網上看到很多問如何更新ListView的信息,采用CusorApater其實很簡單,換cursor就可以 
        cursor.close(); 
        cursor = newCursor; 
    }         

//步驟2:取締requrey的方式,采用後台線程更新形式 
private void addData(String name ,float weight){ 
      ... ... 
    //cursor.requery(); 
    new RefreshList().execute(); 
}

通過ContextMenu來刪除ListView的數據

ContextMenu用戶手指長按某個View觸發的菜單。這裏通過這個例子詳細展開。實現場景:用戶長按某個List元素,則彈出ContextMenu,選擇菜單“Delete”,按下後,彈出AlertDialog,請用戶再去確定是否刪除,確定後將數據從SQLite中刪除,並更新ListView的顯示。具體如下:

Android中的SQLite、ListView、ContextMenu使用學習

Android中的SQLite、ListView、ContextMenu使用學習

Android中的SQLite、ListView、ContextMenu使用學習
    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、id:The row id of the item for which the context menu is being displayed ,在cursorAdaptor中,實際就是表格的_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的形式。 
    private 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-linux_x86/platform-tools目錄下麵有adb命令,使用adb shell,可提供模擬器的console窗口。數據庫文件存放的位置為/data/data/your.app.package/databases/ your-db-name,進入相關的目錄,可以使用#sqlite3 your-db-name,進入相關的數據庫,可以在裏麵執行SQL語句,例如在整個例子中,通過#.schema來查看表格的格式,通過#select * from mytable;可以顯示數據庫的內容。 

最後更新:2017-04-04 07:03:44

  上一篇:go Android 隱藏(刪除) Preference 小結
  下一篇:go android - 自定義(組合)控件 + 自定義控件外觀