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.
思路有了, 就看具体的实现了.
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就可以实时监控并更新显示数据总数了.