博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android ContentObserver
阅读量:6002 次
发布时间:2019-06-20

本文共 3748 字,大约阅读时间需要 12 分钟。

想象一个场景: 有个TextView, 用来显示数据库一个表的数据总数. 用户通过UI界面对数据进行CRUD的操作. 这个TextView如何实时监控并更新显示数据总数?

目录:

第一节 

第二节 

第三节 


这里比较便捷且高效的方案是使用ContentObserver. 前提是已经建立了ContentProvider的支持. 先分析了一些网上广为流传了一个监控SMS变化的Observer例子. 画个图便于ContentObserver的感性认识.

145425217.png



通过这个图, 主要了解3点就可以: 

   1, 建立继承自ContentObserver的对象,实现其onChange()方法.

   2, 在目标Activity中注册和解除.

   3, 在UI线程中, 用Handler接收来自Observer发出的Message, 更新UI.


思路有了, 就看具体的实现了.


一. 首先是建立一个继承自ContentObserver的对象.

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做的事情. 此例子中是重新查询表的数据总数.


二. 在Activity中注册和解除.

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的变化.


三. 在UI线程中, 用Handler接收来自Observer发出的Message, 更新UI.

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. 看起来好像齐全了, 其实还有谁在什么时候通知观察者数据变化了的问题.


四. 在ContentProvider中添加通知数据变化.

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,如需转载请自行联系原作者

你可能感兴趣的文章
Linq to Objects for Java 发布 1.0.1 版本
查看>>
Orchard 候补神器说明
查看>>
java.util.Timer类似于闹钟定时做任务
查看>>
Nancy之从403到错误处理
查看>>
如何设置RHEL6 ADSL(pppoe)实现接入宽带网络
查看>>
使用Python统计端口TCP连接数
查看>>
如何批量增加域用户
查看>>
[Ruby] 模块
查看>>
【高级】思科BGP-MPLS-***在城域网中的部署实战
查看>>
Exchange Server2010系列之二:部署三合一角色(CAS+HT+MBX)
查看>>
世界上最早的算法:辗转相除法(求两个自然数最大公约数)
查看>>
Percona pt-archiver重构版--大表数据归档工具
查看>>
安装Firefly错误-Unable to find vcvarsall.bat
查看>>
SCCM2012 R2实战系列之六:安装客户端代理软件
查看>>
我是怎样不关站通过备案的
查看>>
相对路径和绝对路径错误造成的漏洞
查看>>
演示:思科IPS传感器的命令行初始配置(支持图型化管理)
查看>>
Android Message机制及其应用
查看>>
用SHELL脚本来防SSH暴力破解
查看>>
从等保的角度浅谈数据库系统安全保护机制
查看>>