ContentObserver监听ContentProvider数据变化

 

 

 

 

public class MainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Uri uri = Uri.parse("content://cn.itcast.providers.personprovider/person");
        getContentResolver().registerContentObserver(uri, true, 
        		new PersonContentObserver(new Handler()));
    }
    
    private final class PersonContentObserver extends ContentObserver{

		public PersonContentObserver(Handler handler) {
			super(handler);
		}

		@Override
		public void onChange(boolean selfChange) {
			// sql: select * from person order by personid desc limit 1
			
			ContentResolver resolver = getApplicationContext().getContentResolver();
			Uri uri = Uri.parse("content://cn.itcast.providers.personprovider/person");
			Cursor cursor = resolver.query(uri, null, null, null, "personid desc limit 1");
			if(cursor.moveToFirst()){
				String name = cursor.getString(cursor.getColumnIndex("name"));
				Log.i("AccessContentProviderTest", name);
			}
		}
    	
    }
    
    
}

 

 

 

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

 

 

 


通过这个图, 主要了解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就可以实时监控并更新显示数据总数了.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值