Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android cursor.setNotificationUri()用于什么?_Android_Database_Cursor_Android Contentprovider_Android Contentresolver - Fatal编程技术网

Android cursor.setNotificationUri()用于什么?

Android cursor.setNotificationUri()用于什么?,android,database,cursor,android-contentprovider,android-contentresolver,Android,Database,Cursor,Android Contentprovider,Android Contentresolver,我研究了如何使用ContentProviders和来自 我的看法是: 我们有一个活动,它包含列表视图、简单的应用程序或适配器和游标加载程序。我们还实现了ContentProvider 在活动中我们可以调用getContentResolver().insert(URI,contentValues)通过按钮单击 在ContentProvider的实现中,在insert()方法的末尾,我们调用getContentResolver().notifyChange(URI,null)和我们的游标加载程序将收

我研究了如何使用
ContentProviders
和来自

我的看法是: 我们有一个
活动
,它包含
列表视图
简单的应用程序或适配器
游标加载程序
。我们还实现了
ContentProvider

活动中
我们可以调用
getContentResolver().insert(URI,contentValues)通过按钮单击

ContentProvider
的实现中,在
insert()
方法的末尾,我们调用
getContentResolver().notifyChange(URI,null)
和我们的
游标加载程序
将收到一条消息,它应该重新加载数据并更新UI。此外,如果我们在
SimpleCursorAdapter
中使用
FLAG\u REGISTER\u CONTENT\u OBSERVER
,它也将接收消息,并将调用其方法
onContentChanged()

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

Activity.startManagingCursor(游标)
已弃用,
cursor.requery()
已弃用,因此我看不到任何来自
cursor.setNotificationUri()
的实践意义

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

protected void onChange(boolean selfChange) {
    synchronized (mSelfObserverLock) {
        mContentObservable.dispatchChange(selfChange, null);
        // ...
    }
}
但我无法理解这一点


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

如果调用
cursor.setNotificationUri()
,cursor将知道它是为什么创建的ContentProvider Uri


CursorLoader
为调用
setNotificationUri
时指定的URI使用
上下文
内容解析程序
注册自己的
ForceLoadContentObserver
(扩展了
ContentObserver

因此,一旦
ContentResolver
知道URI的内容已经更改[当您调用
getContext().getContentResolver().notifyChange(URI,contentObserver);
内部
ContentProvider
插入()
更新()
删除()
方法时,就会发生这种情况]它通知所有观察者,包括CursorLoader的
ForceLoadContentObserver


ForceLoadContentObserver
然后将加载程序的mContentChanged标记为true

CursorLoader
为光标注册观察程序,而不是将其注册到URI

看看下面。请注意,
CursorLoader
contentObserver
注册到
cursor

/* 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;
            }
        }
光标
需要调用方法
setNotificationUri()
mSelfObserver
注册到
uri

//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;
        }
    }
contentProvider
insert
update
delete
方法中,需要调用
getContext().getContentResolver().notifyChange(uri,null)
通知对
uri的更改


因此,如果您不调用
cursor#setNotificationUri()
,则如果
CursorLoader
的基础数据发生更改,您的
cursor
将不会收到通知。

我为光标适配器使用一个uri

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Bundle args = new Bundle();
    Uri uri = TemperatureContract.SensorEntry.buildSensorID0AddressUri(mDeviceAddress);
    args.putParcelable("URI", uri);
    getSupportLoaderManager().initLoader(0, args, this);

}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    if (args != null) {
        Uri mUri = args.getParcelable("URI");
        return new CursorLoader(this,
                mUri,
                null, // projection
                null, // selection
                null, // selectionArgs
                null); // sortOrder
    } else {
        return null;
    }
}

我对
insert
delete
方法也做了同样的操作。

即使我迟到了,我的问题是,对于使用此URI查询我们的ContentProvider的另一个应用程序,这是否可能?
@Override
public int update(
        Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
    final int match = sUriMatcher.match(uri);
    int rowsUpdated;
    switch (match) {
        case ...:
            break;
        case SENSOR_BY_ID_AND_ADDRESS:
            String sensorId = TemperatureContract.SensorEntry.getSensorIdFromUri(uri);
            String sensorAddress = TemperatureContract.SensorEntry.getSensorAddressFromUri(uri);
            rowsUpdated = db.update(
                    TemperatureContract.SensorEntry.TABLE_NAME, values, "sensorid = ? AND address = ?", new String[]{sensorId, sensorAddress});
            if (rowsUpdated != 0) {
                Uri otheruri = TemperatureContract.SensorEntry.buildSensorID0AddressUri(sensorAddress);
                getContext().getContentResolver().notifyChange(otheruri, null);
            }
            break;
        case ...:
            break;
        default:
            throw new UnsupportedOperationException("Unknown uri: " + uri);
    }
    if (rowsUpdated != 0) {
        getContext().getContentResolver().notifyChange(uri, null);
    }
    return rowsUpdated;