http://blog.youkuaiyun.com/oney139/article/details/7932654
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, mySortOrder);
- //Cursor ContentResolver Uri 之间的关系是什么
- c.setNotificationUri(getContext().getContentResolver(), uri);
- return c;
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, mySortOrder);
//Cursor ContentResolver Uri 之间的关系是什么
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
- long rowId = db.insert(NOTES_TABLE_NAME, null, contentValues);
- if(rowId > 0) {
- Uri newUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, rowId);
- //这里的 ContentResolver.notifyChange(Uri,null)做了什么工作?
- //和 Cursor.setNotificationUri()有什么关系
- getContext().getContentResolver().notifyChange(newUri, null);
- return newUri;
- } else {
- // android.database.SQLException
- throw new SQLException("Failed to insert row into " + uri);
- }
long rowId = db.insert(NOTES_TABLE_NAME, null, contentValues);
if(rowId > 0) {
Uri newUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, rowId);
//这里的 ContentResolver.notifyChange(Uri,null)做了什么工作?
//和 Cursor.setNotificationUri()有什么关系
getContext().getContentResolver().notifyChange(newUri, null);
return newUri;
} else {
// android.database.SQLException
throw new SQLException("Failed to insert row into " + uri);
}
在实现 ContentProvider 的query 时,一般都有下面几行代码:
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, mySortOrder);
- //这一行的代码的作用?
- c.setNotificationUri(getContext().getContentResolver(), uri);
- return c;
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, mySortOrder);
//这一行的代码的作用?
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
下面具体说下注释的那行的作用?
从字面上看 setNotificationUri, 即 Uri 有改变时对本 Cursor 发出通知.
查看 AbstractCursor.setNotificationUri 源代码如下:
- public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
- mContentResolver = cr;
- mNotifyUri = notifyUri;
- mSelfObserver = new SelfContentObserver(this);
- //cr.registerContentObserver(notifyUri, mSelfObserver)
- mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
- }
public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
mContentResolver = cr;
mNotifyUri = notifyUri;
mSelfObserver = new SelfContentObserver(this);
//cr.registerContentObserver(notifyUri, mSelfObserver)
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
}
这个方法的作用就是在 ContentResolver上注册一个 Observer,
当 ContentResolver.notifyChange 时将调用已经注册的 ContentObserver, 你可以通过调用 ContentResolver.registerContentObserver 明确的给 ContentReselover注册观察者,
在这里我们并没有明确的调用 registerContentReselover方法, 而是通过 Cursor.setNotificationUri 间接的注册了一个 ContentObserver.
这个间接注册的好处是什么呢?
间接注册时的 ContentObserver 是 AbstractCursor的一个内部类, 这个以内部类形式存在的 ContentObserver把 AbstractCursor关联进去.
总体上的过程为:
- //这个 Cursor 会被 Context.getContentResolver().query() 返回
- Cursor c = SQLiteDatabase.query();
- // 在 ContentResolver上注册一个 ContentObserver
- c.setNotificationUri(ContentResolver,Uri)
- //如果ContentObserver参数为null, 则ContentResolver会通知上一步注册的ContentObserver
- getContentResolver().notifyChange(Uri,ContentObserver)
- //Abstract Cursor 源码中的 setNotificationUri方法下的
- new SelfContentObserver(this) //会获得ContentResolver发出的通知
//这个 Cursor 会被 Context.getContentResolver().query() 返回
Cursor c = SQLiteDatabase.query();
// 在 ContentResolver上注册一个 ContentObserver
c.setNotificationUri(ContentResolver,Uri)
//如果ContentObserver参数为null, 则ContentResolver会通知上一步注册的ContentObserver
getContentResolver().notifyChange(Uri,ContentObserver)
//Abstract Cursor 源码中的 setNotificationUri方法下的
new SelfContentObserver(this) //会获得ContentResolver发出的通知
SelfContentObserver会通知和其关联的Cursor(初始化SelfContentObserver时进行关联)
Cursor会调用 onChange 通知自己的 ContentObserver. 其中默认的 ContentObserver是 CursorAdapter
也就是说 Cursor 也有 ContentObserver, 而它的默认 ContentObserver是在这个时候设立的:
- //在这个构造数内会设置 Cursor 的观察者为 CursorAdapter,具体可以查看源代码跟踪一下
- SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.notes_list_item,
- c/* 指Cursor */, new String[]{NotePad.Notes.TITLE}, new int[]{R.id.text1});
//在这个构造数内会设置 Cursor 的观察者为 CursorAdapter,具体可以查看源代码跟踪一下
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.notes_list_item,
c/* 指Cursor */, new String[]{NotePad.Notes.TITLE}, new int[]{R.id.text1});
另外Uri参数的用处没有搞太清楚,但总体上是:
content://com.example.notepad/notes/5 这种Uri也会引起 content://com.example.notepad/notes 这种Uri的改变
http://aijiawang-126-com.iteye.com/blog/812004
监测database的改变--notifyChange
我们在ContentProvider的insert,update,delete等改变之后调用getContext().getContentResolver().notifyChange(uri, null);这样就通知那些监测databases变化的observer了,而你的observer可以在一个service里面注册。
以Downloadmanger为例子:
定义ContentObserver,并且在onChange里做你想做的事情。
在DownloadService的onCreate中注册:
可以参考以下文章:
http://hi.baidu.com/lck0502/blog/item/a818258f304b61e0f01f3691.html
以Downloadmanger为例子:
定义ContentObserver,并且在onChange里做你想做的事情。
- /**
- * Receives notifications when the data in the content provider changes
- */
- private class DownloadManagerContentObserver extends ContentObserver {
- public DownloadManagerContentObserver() {
- super(new Handler());
- }
- /**
- * Receives notification when the data in the observed content
- * provider changes.
- */
- public void onChange(final boolean selfChange) {
- if (Constants.LOGVV) {
- Log.v(Constants.TAG, "Service ContentObserver received notification");
- }
- updateFromProvider();
- }
- }
/**
* Receives notifications when the data in the content provider changes
*/
private class DownloadManagerContentObserver extends ContentObserver {
public DownloadManagerContentObserver() {
super(new Handler());
}
/**
* Receives notification when the data in the observed content
* provider changes.
*/
public void onChange(final boolean selfChange) {
if (Constants.LOGVV) {
Log.v(Constants.TAG, "Service ContentObserver received notification");
}
updateFromProvider();
}
}
在DownloadService的onCreate中注册:
- public void onCreate() {
- super.onCreate();
- if (Constants.LOGVV) {
- Log.v(Constants.TAG, "Service onCreate");
- }
- mDownloads = Lists.newArrayList();
- mObserver = new DownloadManagerContentObserver();
- getContentResolver().registerContentObserver(Downloads.CONTENT_URI,
- true, mObserver);
- .....}
public void onCreate() {
super.onCreate();
if (Constants.LOGVV) {
Log.v(Constants.TAG, "Service onCreate");
}
mDownloads = Lists.newArrayList();
mObserver = new DownloadManagerContentObserver();
getContentResolver().registerContentObserver(Downloads.CONTENT_URI,
true, mObserver);
......}
- /**
- * Cleans up when the service is destroyed
- */
- public void onDestroy() {
- getContentResolver().unregisterContentObserver(mObserver);
- if (Constants.LOGVV) {
- Log.v(Constants.TAG, "Service onDestroy");
- }
- super.onDestroy();
- }
/**
* Cleans up when the service is destroyed
*/
public void onDestroy() {
getContentResolver().unregisterContentObserver(mObserver);
if (Constants.LOGVV) {
Log.v(Constants.TAG, "Service onDestroy");
}
super.onDestroy();
}
可以参考以下文章:
http://hi.baidu.com/lck0502/blog/item/a818258f304b61e0f01f3691.html