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标记为trueCursorLoader
为光标注册观察程序,而不是将其注册到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;