setNotificationUri和ContentResolver.notifyChange

http://blog.csdn.net/oney139/article/details/7932654

  1. SQLiteDatabase db = mOpenHelper.getReadableDatabase();  
  2. Cursor c = qb.query(db, projection, selection, selectionArgs, nullnull, mySortOrder);  
  3. //Cursor ContentResolver Uri 之间的关系是什么  
  4. c.setNotificationUri(getContext().getContentResolver(), uri);  
  5. 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;
[java] view plain copy print ?
  1. long rowId = db.insert(NOTES_TABLE_NAME, null, contentValues);  
  2. if(rowId > 0) {  
  3.     Uri newUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, rowId);  
  4.         //这里的 ContentResolver.notifyChange(Uri,null)做了什么工作?  
  5.         //和 Cursor.setNotificationUri()有什么关系  
  6.         getContext().getContentResolver().notifyChange(newUri, null);  
  7.     return newUri;  
  8. else {  
  9.     // android.database.SQLException  
  10.     throw new SQLException("Failed to insert row into " + uri);  
  11. }  
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 时,一般都有下面几行代码:

[java] view plain copy print ?
  1. SQLiteDatabase db = mOpenHelper.getReadableDatabase();  
  2. Cursor c = qb.query(db, projection, selection, selectionArgs, nullnull, mySortOrder);  
  3. //这一行的代码的作用?   
  4. c.setNotificationUri(getContext().getContentResolver(), uri);  
  5. 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 源代码如下:

[java] view plain copy print ?
  1. public void setNotificationUri(ContentResolver cr, Uri notifyUri) {  
  2.     mContentResolver = cr;  
  3.     mNotifyUri = notifyUri;  
  4.     mSelfObserver = new SelfContentObserver(this);  
  5.     //cr.registerContentObserver(notifyUri, mSelfObserver)  
  6.     mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);  
  7. }  
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关联进去.

总体上的过程为:

[java] view plain copy print ?
  1. //这个 Cursor 会被 Context.getContentResolver().query() 返回  
  2. Cursor c = SQLiteDatabase.query();  
  3. // 在 ContentResolver上注册一个 ContentObserver  
  4. c.setNotificationUri(ContentResolver,Uri)  
  5. //如果ContentObserver参数为null, 则ContentResolver会通知上一步注册的ContentObserver  
  6. getContentResolver().notifyChange(Uri,ContentObserver)  
  7. //Abstract Cursor 源码中的 setNotificationUri方法下的  
  8. 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是在这个时候设立的:

[java] view plain copy print ?
  1. //在这个构造数内会设置 Cursor 的观察者为 CursorAdapter,具体可以查看源代码跟踪一下  
  2. SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.notes_list_item,   
  3.                 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里做你想做的事情。
Java代码 复制代码  收藏代码
  1. /**  
  2.      * Receives notifications when the data in the content provider changes 
  3.      */  
  4.     private class DownloadManagerContentObserver extends ContentObserver {   
  5.   
  6.         public DownloadManagerContentObserver() {   
  7.             super(new Handler());   
  8.         }   
  9.   
  10.         /**  
  11.          * Receives notification when the data in the observed content 
  12.          * provider changes.  
  13.          */  
  14.         public void onChange(final boolean selfChange) {   
  15.             if (Constants.LOGVV) {   
  16.                 Log.v(Constants.TAG, "Service ContentObserver received notification");   
  17.             }   
  18.             updateFromProvider();   
  19.         }   
  20.   
  21.     }  
/**
     * 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中注册:
Java代码 复制代码  收藏代码
  1. public void onCreate() {   
  2.        super.onCreate();   
  3.        if (Constants.LOGVV) {   
  4.            Log.v(Constants.TAG, "Service onCreate");   
  5.        }   
  6.   
  7.        mDownloads = Lists.newArrayList();   
  8.   
  9.        mObserver = new DownloadManagerContentObserver();   
  10.        getContentResolver().registerContentObserver(Downloads.CONTENT_URI,   
  11.                true, mObserver);   
  12. .....}  
 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);
......}


Java代码 复制代码  收藏代码
  1. /**  
  2.     * Cleans up when the service is destroyed  
  3.     */  
  4.    public void onDestroy() {   
  5.        getContentResolver().unregisterContentObserver(mObserver);   
  6.        if (Constants.LOGVV) {   
  7.            Log.v(Constants.TAG, "Service onDestroy");   
  8.        }   
  9.        super.onDestroy();   
  10.    }  
 /**
     * 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

 

你可能感兴趣的:(Android开发)