本文共 3748 字,大约阅读时间需要 12 分钟。
想象一个场景: 有个TextView, 用来显示数据库一个表的数据总数. 用户通过UI界面对数据进行CRUD的操作. 这个TextView如何实时监控并更新显示数据总数?
目录:
第一节
第二节
第三节
这里比较便捷且高效的方案是使用ContentObserver. 前提是已经建立了ContentProvider的支持. 先分析了一些网上广为流传了一个监控SMS变化的Observer例子. 画个图便于ContentObserver的感性认识.
通过这个图, 主要了解3点就可以:
1, 建立继承自ContentObserver的对象,实现其onChange()方法.
2, 在目标Activity中注册和解除.
3, 在UI线程中, 用Handler接收来自Observer发出的Message, 更新UI.
思路有了, 就看具体的实现了.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class TAGContentObserver extends ContentObserver{ private Context mContext; private Handler mHandler; public static final int TAG_DB_CHANGE = 921 ; public TAGContentObserver(Context context, Handler handler) { super (handler); mContext = context; mHandler = handler; } @Override public void onChange( boolean selfChange) { //数据变化, 重新查询最新结果. Cursor cursor = mContext.getContentResolver().query(TAGDBOpenHelper.CONTENT_URI, null , null , null , null ); //发送Message. 此Handler定义在Activity中, 拆开Message得到结果更新TextView. mHandler.obtainMessage(TAG_DB_CHANGE, cursor.getCount(), 0 ).sendToTarget(); } } |
重点是实现其onChange()方法, 如注释所写. onChange可以理解为在得到数据变化的通知之后, Observer做的事情. 此例子中是重新查询表的数据总数.
1 2 3 | //注册观察者 ContentObserver observer = new TAGContentObserver(MainActivity. this , mMyHandler); getContentResolver().registerContentObserver(TAGDBOpenHelper.CONTENT_URI, true , observer); |
1 2 | //解除观察者 getContentResolver().unregisterContentObserver(observer); |
注册和解除可以根据需要, 比如分别放在Activity的onCreate()和onDestroy()方法中. 关于这个CONTENT_URI, 是自定义的, 如:
1 2 3 | public static final String TABLE_NAME_TAG = "tag" ; public static final String AUTHORITY = "com.lichen.tagprovider" ; public static final Uri CONTENT_URI = Uri.parse( "content://" +TAGDBOpenHelper.AUTHORITY+ "/" +TABLE_NAME_TAG); |
此Observer的目的可以说是监听或者观察这个URI的变化.
1 2 3 4 5 6 7 8 9 | @Override public void handleMessage(Message msg) { switch (msg.what) { case TAGContentObserver.TAG_DB_CHANGE: TextView tagNum = (TextView) findViewById(R.id.tag_total_num); tagNum.setText( "TAG总数: " + msg.arg1); break ; } } |
到这里, 注册观察者Observer, 数据变化后重新查询数据库, 得到结果异步用Handler来更新UI. 看起来好像齐全了, 其实还有谁在什么时候通知观察者数据变化了的问题.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | @Override public Uri insert(Uri uri, ContentValues values) { db = dbHelper.getWritableDatabase(); long rowId = db.insert(TAGDBOpenHelper.TABLE_NAME_TAG, "" , values); if (rowId > 0 ) { Uri newUrl = ContentUris.withAppendedId(TAGDBOpenHelper.CONTENT_URI, rowId); //通知数据变化 getContext().getContentResolver().notifyChange(newUrl, null ); return newUrl; } return null ; } @Override public int delete(Uri uri, String where, String[] whereArgs) { db = dbHelper.getWritableDatabase(); int count = 0 ; switch (matcher.match(uri)) { case TAGDBOpenHelper.TAG: count = db.delete(TAGDBOpenHelper.TABLE_NAME_TAG, where, whereArgs); break ; case TAGDBOpenHelper.TAG_ID: long parseId = ContentUris.parseId(uri); where = " _id = " + parseId ; count = db.delete(TAGDBOpenHelper.TABLE_NAME_TAG, where, null ); break ; } //通知数据变化 getContext().getContentResolver().notifyChange(uri, null ); return count; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { db = dbHelper.getReadableDatabase(); int match = matcher.match(uri); Cursor cursor = null ; switch (match) { case TAGDBOpenHelper.TAG: cursor = db.query(TAGDBOpenHelper.TABLE_NAME_TAG, null , null , null , null , null , null ); cursor.setNotificationUri(getContext().getContentResolver(), uri); //通知数据变化 break ; } return cursor; } |
这样, 这个TextView就可以实时监控并更新显示数据总数了.
本文转自chainli 51CTO博客,原文链接:http://blog.51cto.com/lichen/1205628,如需转载请自行联系原作者