cursor.setNotificationUri()用于什么?

anb*_*ber 23 database android cursor android-contentresolver android-contentprovider

我在本教程中研究了如何使用ContentProviders和加载器

我是怎么看的:我们有一个ActivityListView,SimpleCursorAdapterCursorLoader.我们也实施ContentProvider.

Activity我们可以调用getContentResolver().insert(URI, contentValues);通过点击一个按钮.

在我们的实现中ContentProvider,在insert()方法结束时,我们调用getContentResolver().notifyChange(URI, null);并且我们CursorLoader将收到消息,它应该重新加载数据并更新UI.此外,如果我们FLAG_REGISTER_CONTENT_OBSERVERSimpleCursorAdapter其中使用它也将接收消息并且onContentChanged()将调用其方法.

因此,如果我们插入,更新或删除数据,我们的ListView将会更新.

Activity.startManagingCursor(cursor);已弃用,cursor.requery()已弃用,因此我没有看到任何练习意义 cursor.setNotificationUri().

我查看了setNotificationUri()方法的源代码,发现它调用mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver)了方法.也是CursorLoader一样的.最后,游标将接收消息,并在Cursor内部调用以下方法:

protected void onChange(boolean selfChange) {
    synchronized (mSelfObserverLock) {
        mContentObservable.dispatchChange(selfChange, null);
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

但我无法理解这一点.

所以我的问题是:我们为什么要叫cursor.setNotificationUri()query()我们的方法ContentProvider实现?

Mic*_*riv 31

如果你调用Cursor.setNotificationUri(),Cursor将知道它为其创建的ContentProvider Uri.

CursorLoader注册自己ForceLoadContentObserver(延伸ContentObserver)与ContextContentResolver的URI在调用时指定setNotificationUri.

所以,一旦ContentResolver知道URI的内容已被更改 [出现这种情况,当你调用getContext().getContentResolver().notifyChange(uri, contentObserver);里面ContentProviderinsert(),update()而且delete()方法]它通知所有观察员包括CursorLoader的ForceLoadContentObserver.

ForceLoadContentObserver 然后将Loader的mContentChanged标记为true


小智 14

CursorLoader注册游标的观察者,而不是 URI.

查看下面的CursorLoader的源代码.请注意,CursorLoader注册contentObservercursor.

/* Runs on a worker thread */
    @Override
    public Cursor loadInBackground() {
        synchronized (this) {
            if (isLoadInBackgroundCanceled()) {
                throw new OperationCanceledException();
            }
            mCancellationSignal = new CancellationSignal();
        }
        try {
            Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection,
                    mSelectionArgs, mSortOrder, mCancellationSignal);
            if (cursor != null) {
                try {
                    // Ensure the cursor window is filled.
                    cursor.getCount();
                    cursor.registerContentObserver(mObserver);
                } catch (RuntimeException ex) {
                    cursor.close();
                    throw ex;
                }
            }
            return cursor;
        } finally {
            synchronized (this) {
                mCancellationSignal = null;
            }
        }
Run Code Online (Sandbox Code Playgroud)

Cursor需要调用方法setNotificationUri()来注册mSelfObserveruri.

//AbstractCursor.java
public void setNotificationUri(ContentResolver cr, Uri notifyUri, int userHandle) {
        synchronized (mSelfObserverLock) {
            mNotifyUri = notifyUri;
            mContentResolver = cr;
            if (mSelfObserver != null) {
                mContentResolver.unregisterContentObserver(mSelfObserver);
            }
            mSelfObserver = new SelfContentObserver(this);
            mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver, userHandle); // register observer to the uri
            mSelfObserverRegistered = true;
        }
    }
Run Code Online (Sandbox Code Playgroud)

里面contentProviderinsert,update,delete方法,你需要打电话getContext().getContentResolver().notifyChange(uri, null);通知更改为uri观察员.

因此,如果您不打电话cursor#setNotificationUri(),CursorLoader如果基础数据uri发生变化,您将不会收到通知.