通过ContentObserver监听数据库某表的增加、删除、更新动作,实现listView异步单项Item的刷新
来源:互联网 发布:sql server 2008 sa 编辑:程序博客网 时间:2024/06/05 07:07
如何使用ContentObserver
使用ContentObserver的步骤:
1.继承ContentObserver,重载父类的构造方法,实现onChange方法,可根据其中的Uri参数区分不同的动作
2. 注册内容观察者。
context.getContentResolover().registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)
功能:为指定的Uri注册一个ContentObserver派生类实例,当给定的Uri发生改变时,回调该实例对象处理。
参数:uri 需要观察的Uri(如:content://example.message/messages 为监听messages表)
notifyForDescendents 为false 表示精确匹配,即只匹配该Uri
为true 表示可以同时匹配其派生的Uri
observer 为自己实现的ContentObserver
注意:此处notifyForDescendents值设置为true,才能做区分增加、删除等动作。
3. 在退出或不需要监听的时候,执行反注册:如在onDestroy()方法中调用public final void unregisterContentObserver(ContentObserver
observer)
功能:取消对给定Uri的观察
参数: observer ContentObserver的派生类实例
参考代码如下:
private class MessageObserver extends ContentObserver {// 自定义ContentObserver public MessageObserver(Handler handler) { super(handler); } @SuppressLint("NewApi") @Override public void onChange(boolean selfChange, Uri uri) { Log.d(TAG, " self change " + selfChange + " Uri " + uri); // parse Uri, insert, delete, update int operation = getOperationTypeByUri(uri);//根据Uri获取动作类型(增加、删除等) mCurrentMessageId = getIdByUri(uri);//根据Uri获取改变的mID Log.d(TAG, "--operation:"+operation+"--mCurrentMessageId:"+mCurrentMessageId); doRefreshByOperation(operation,mCurrentMessageId); //执行数据更新操作 super.onChange(selfChange, uri); } } ----------- //根据Uri获取动作类型 private int getOperationTypeByUri(Uri uri){ int operationType = -1; String strUri = uri.toString(); int endIndex = strUri.lastIndexOf("/"); int beginIndex = endIndex - 6;// insert/update/delete string-size is 6 String type = strUri.substring(beginIndex, endIndex); Log.d(TAG, "--getOperationTypeByUri--type:"+type); if(!TextUtils.isEmpty(type)){ if("insert".equals(type)){ operationType = OPERATION_INSERT; }else if("update".equals(type)){ operationType = OPERATION_UPDATE; }else if("delete".equals(type)){ operationType = OPERATION_DELETE; } } Log.d(TAG, "--getOperationTypeByUri--operationType:"+operationType); return operationType; } --------------- //根据Uri获取改变的mID private String getIdByUri(Uri uri){ String id = ""; if(null == uri){ Log.e(TAG, "--getIdbyUri--uri is null, return"); return id; } String strUri = uri.toString(); int lastIndex = strUri.lastIndexOf("/"); id = strUri.substring(lastIndex + 1, strUri.length()); Log.d(TAG, "--getIdByUri--id:"+id); return id; } --------------- //根据数据库动作类型,执行不同的操作(此处实现的是聊天页面listView异步刷新单个Item) private void doRefreshByOperation(int operation, String id){ if(null == mSmsProviderHelp){ Log.e(TAG, "--doRefreshByOperation mSmsProviderHelp is null, return"); return; } switch (operation) { case OPERATION_INSERT: mSmsProviderHelp.startQueryMessageById(mQueryHandler, SmsProviderHelp.MESSAGES_INSERT_BY_ID_TOKEN, id,mPhoneNumber);//根据mID查询单条数据 break; case OPERATION_UPDATE: mSmsProviderHelp.startQueryMessageById(mQueryHandler, SmsProviderHelp.MESSAGES_UPDATE_BY_ID_TOKEN, id,mPhoneNumber);//根据mID查询单条数据 break; case OPERATION_DELETE: // delete one from arraylist int mID = -1; try { mID = Integer.parseInt(id); } catch (NumberFormatException e) { e.printStackTrace(); } int deletePosi = mSparseArray.get(mID, -1); Log.d(TAG, "--deletePosi:"+deletePosi+"--mID:"+mID); if(deletePosi > -1 && null != mDataList && deletePosi < mDataList.size()){ mDataList.remove(deletePosi); mMessageAdapter.notifyDataSetChanged(); } break; default: break; } }
实现ContentProvider,对数据库的增加、删除、更新动作进行通知
上面实现的ContentObserver,只是进行监听,当动作变化时需要执行的逻辑放在onChange中。
那么,如何进行通知呢?
答案就是:继承ContentProvider,需要自己实现其中的insert、delete、update方法,发送不同的Uri出去。
参考代码如下:
public class SmsProvider extends ContentProvider {@Override public int delete(Uri url, String where, String[] whereArgs) { String table = TABLE_SMS; int count; int match = sURLMatcher.match(url); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); switch (match) { case ACTION_SMS: table = TABLE_SMS; break; case ACTION_THREAD: table = TABLE_THREAD; break; default: throw new IllegalArgumentException("Unknown URL" +url.toString()); } count = db.delete(table, where, whereArgs); if (count > 0) { String rowId = ""; if(null != whereArgs){ rowId = whereArgs[0]; } Uri deleteUri = Uri.withAppendedPath(url, "delete/"+rowId);//此处为重点,构造了一个Uri发送出去 Log.d(TAG, "--deleteUri:"+deleteUri); notifyChange(deleteUri); } return count; }private void notifyChange(Uri uri) { ContentResolver cr = getContext().getContentResolver(); cr.notifyChange(uri, null); } @Override public Uri insert(Uri url, ContentValues initialValues) { ... rowID = db.insert(table, "body", values); if (rowID > 0) { Uri insertUri = Uri.withAppendedPath(url, "insert/"+rowID);//此处为重点,构造了一个Uri发送出去 Log.d(TAG, "--insertUrl:"+insertUri); notifyChange(insertUri); Uri uri = Uri.parse("content://" + table + "/" + rowID); Log.d(TAG, "insert " + uri + " succeeded"); return uri; }@Override public int update(Uri url, ContentValues values, String where, String[] whereArgs) { ... count = db.update(table, values, where, whereArgs); if (count > 0) { Log.d(TAG, "update " + url + " succeeded"+"values"+values.toString()+"where"+where); String rowId = ""; if(null != whereArgs){ rowId = whereArgs[0]; } Uri updateUri = Uri.withAppendedPath(url, "update/"+rowId);//此处为重点,构造了一个Uri发送出去 Log.d(TAG, "--updateUri:"+updateUri); notifyChange(updateUri); } return count;
代码描述:
在delete方法中,判断删除成功时,构造带有“delete/mID”的Uri.
在insert方法中,判断增加成功时,构造带有“insert/mID”的Uri
在update方法中,判断更新成功时,构造带有“update/mID”的Uri
最后通过调用
ContentResolver cr = getContext().getContentResolver();
cr.notifyChange(uri, null);// null表示所有的observer都能收到
发送通知出去。
可以实现的功能
通过Uri区分不同的数据库动作后。可以根据需要实现不同的功能。
比如:聊天消息页面的异步单项Item刷新流程如下:
流程:
1. 区分message insert update delete 动作,通过messageId查询单条数据
2. 在onchange方法中根据URI区分各种动作。
3. 维护一个map保存position和messageId优化性能
4. 对onChange方法后的刷新逻辑做判断。
@1若为Insert操作,总结起来就是:把数据插入到最后面,调用notifydatasetchanged.
@2.为update操作,根据messageId,单独查询该消息,查询完成后,把该messageId对应的Item数据更新,调用notifidatasetchanged.
@3.为delete操作,根据messageId,找到对应的position,从datalist中remove该Item,调用notifidatasetchanged
另外,可参考另一篇文章:通过AsyncQueryHandler异步对数据库进行增删查操作
若对你还有点用处,那就是本篇文章的意义所在。谢谢。
- 通过ContentObserver监听数据库某表的增加、删除、更新动作,实现listView异步单项Item的刷新
- ListView中Item控件监听及异步刷新的实现
- ContentObserver实现数据库的监听
- ListView的单项刷新
- ListView的单项刷新
- 使用ContentObserver监听短信数据库的变化
- listView的item向左滑动实现删除
- Android ContentObserver实现数据库监听
- Android的ContentObserver类,实现监听手机短信
- Android listview动态添加删除更新带ProgressBar的Item
- ContentObserver 监听(监听自己数据库的变化)
- android的content provider之二:添加数据库属性及用ContentObserver实现数据库的监听
- android的content provider之二:添加数据库属性及用ContentObserver实现数据库的监听
- ListView通过自定义适配器来显示数据并对Item项以及子view项的控件实现监听.
- ListView通过自定义适配器来显示数据并对Item项以及子view项的控件实现监听.
- ListView通过自定义适配器来显示数据并对Item项以及子view项的控件实现监听
- 监听listview中item有控件点击事件的变化,更新listview
- 关于使用ContentObserver监听不到删除短信会话的解决方案
- Log4Qt使用笔记(三)
- redis5种类型支持的场景
- Nginx 安装部署
- Linux安装Redis,设置密码,使用Java连接
- 微信小程序获取获取openid
- 通过ContentObserver监听数据库某表的增加、删除、更新动作,实现listView异步单项Item的刷新
- Java面试之路(一)Java基础部分
- Maven编译打包过程(clean install)中遇到相关jdk版本导致的问题
- 杭电oj1865
- 透明度测试与透明度混合详解《unity shader入门精要》学习笔记
- LINTCODE————最小划分
- 程序员 30 岁前,该如何规划自己的职业发展?
- 淡入淡出js 原生实现以及css 实现方法
- 最不可思议的巧合,这些电影一定是穿越者拍的了!