标签:
今天学习sqlite的时候,用到了simpleCursorAdapter.SimpleCursorAdapter是Android专门为了连接数据库与视图而产生的。他是将从数据库表中获取的数据显示到ListView的桥梁。按照网上教程,我利用ListView体现SimpleCursorAdapter的用法。
1 ListView list=(ListView)findViewByID(R.id.listview); 2 SQLiteDatabase dbread=db.getReadableDatabase(); 3 Cursor cur=dbread.query("user",null,null,null,null,null,null); 4 adapter=new SimpleCursorAdapter(this,R.layout.layout,cur,new String[]{"name","sex"},new int[]{R.id.name,R.id.sex}); 5 listview.setAdapter(sca);
但是,调试的时候应用报错,column ‘_id‘ does not exist。然后才看到教程里写必须要求我们的数据库中有一列,_id;SimpleCursorAdapter非常傲娇, 如果没有这列,就不干了。
还有两个问题,1.SimpleCursorAdapter 中间出现了一道横线,那说明这个函数已经过时,代替的函数是什么.2.当数据库数据更新时,使用adapter.notifyDataSetChanged(),列表并未更新,那么如何保证UI及时更新?
找到的代替SimplecursorAdapter构造方法的函数是:SimpleCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to,int flags) 相较于之前的,仅仅多了一个 flags。flags在这里是用来标识当数据发生改变调用onContentChanged()的时候是否通知ContentProvider数据改变。对应有两个常数:CursorAdapter。FLAG_AUTO_REQUERY和CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER。前者在api11后不推荐使用,就不在叙述。后者的作用是在 Cursor 上注册一个内容监测器,并在其发出通知时调用 onContentChanged() 方法。
如果无需监听ContentProvider的改变,或者,在CursorAdapter中使用了CursorLoader(他会为你注册一个内容监测器),则可以传0。
在UI更新方面,我找到三个方法:
cursor.requery();
adapter.notifyDataSetChanged();
adapter.swapCursor(newCursor);
adapter.notifyDataSetChanged();
adapter.changeCursor(newCursor);
adapter.notifyDataSetChanged();
第一种方法,requery被画上了横线,并且这个方法测试失败了。
第二种方法和第三种方法都成功了。查阅资料,swapCursor和changeCursor两种方法的区别介绍如下:
1 public Cursor swapCursor(Cursor newCursor) { 2 if (newCursor == mCursor) { 3 return null; 4 } 5 Cursor oldCursor = mCursor; 6 if (oldCursor != null) { 7 if (mChangeObserver != null) oldCursor.unregisterContentObserver(mChangeObserver); 8 if (mDataSetObserver != null) oldCursor.unregisterDataSetObserver(mDataSetObserver); 9 } 10 mCursor = newCursor; 11 if (newCursor != null) { 12 if (mChangeObserver != null) newCursor.registerContentObserver(mChangeObserver); 13 if (mDataSetObserver != null) newCursor.registerDataSetObserver(mDataSetObserver); 14 mRowIDColumn = newCursor.getColumnIndexOrThrow("_id"); 15 mDataValid = true; 16 // notify the observers about the new cursor 17 notifyDataSetChanged(); 18 } else { 19 mRowIDColumn = -1; 20 mDataValid = false; 21 // notify the observers about the lack of a data set 22 notifyDataSetInvalidated(); 23 } 24 return oldCursor; 25 }
swapCursor 交换了一个新的 Cursor,返回旧的Cursor,它并未将旧Cursor关闭
1 public void changeCursor(Cursor cursor) { 2 Cursor old = swapCursor(cursor); 3 if (old != null) { 4 old.close(); 5 } 6 }
changeCursor则替换将原来的 Cursor关闭了。
如果使用了CursorLoader(这真是一个好东西),它会管理Cursor,不需要我们自己关闭Cursor,loader会完成。我们只需实现下面三种方法即可
1 // Called when a new Loader needs to be created 2 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 3 // Now create and return a CursorLoader that will take care of 4 // creating a Cursor for the data being displayed. 5 return new CursorLoader(this, ContactsContract.Data.CONTENT_URI, 6 PROJECTION, SELECTION, null, null); 7 } 8 9 // Called when a previously created loader has finished loading 10 public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 11 // Swap the new cursor in. (The framework will take care of closing the 12 // old cursor once we return.) 13 mAdapter.swapCursor(data); 14 } 15 16 // Called when a previously created loader is reset, making the data unavailable 17 public void onLoaderReset(Loader<Cursor> loader) { 18 // This is called when the last Cursor provided to onLoadFinished() 19 // above is about to be closed. We need to make sure we are no 20 // longer using it. 21 mAdapter.swapCursor(null);
参考资料:http://stackoverflow.com/questions/11093380/what-to-set-cursoradaptercontext-context-cursor-c-int-flags-to-in-order-to-m
http://www.blogc.at/2014/03/03/swapcursor-vs-changecursor-whats-the-difference/
http://developer.android.com/reference/android/widget/CursorAdapter.html#CursorAdapter(android.content.Context, android.database.Cursor, int)
标签:
原文地址:http://www.cnblogs.com/AimeeKing/p/4699485.html