是否有必要同时实现LoaderCallbacks和OnLoadCompleteListener获得在ContentProvider的变化的通知? [英] Is it necessary to implement both LoaderCallbacks and OnLoadCompleteListener to get notifications of changes in a ContentProvider?
问题描述
我这是使用装载机
s到获得在这也正由 IntentService
。我收到的数据从装载机
通过 LoaderCallbacks
执行,这是工作的罚款。
我也使用 ContentResolver的#有NotifyChange(URI,ContentObserver)
触发重新加载。然而,当我把这个只适用光标#setNotificationUri(URI)
事先
我能找到没有提及任何文档中的后一种方法,它似乎在事实上,这可能会导致死机:又见
<一个href=\"http://stackoverflow.com/questions/14956608/illegalstateexception-attempt-to-re-open-an-already-closed-object-in-simplecur\">IllegalStateException &QUOT;试图重新打开一个已关闭的对象&QUOT;在SimpleCursorAdapter从ContentProvider的
然而,如果没有对光标此调用
的 LoaderCallbacks#onLoadFinished(装载机&LT;游标&gt;中光标)
是只有初始加载之后,并通知后未命中。难道我也的需要实施 OnLoadCompleteListener
做的,好了,完全一样的东西?
的ContentProvider
查询方法:
类MyContentProvider扩展ContentProvider的{
// ... @覆盖
公共光标查询(URI URI,字符串[]投影,字符串的选择,
的String [] selectionArgs两个,字符串中将sortOrder){
SQLiteDatabase分贝= mOpenHelper.getReadableDatabase();
游标查询= db.query(getTableName时(URI),投影,选择,selectionArgs两个,NULL,NULL,中将sortOrder);
query.setNotificationUri(的getContext()getContentResolver(),URI);
返回查询;
}// ...
}
典型 LoaderCallbacks
:
LoaderCallbacks&LT;&光标GT; mCallbacks =新LoaderCallbacks&LT;&光标GT;(){ @覆盖
公共无效onLoaderReset(装载机&LT;&光标GT;装载机){
mArticleAdapter.swapCursor(NULL);
} @覆盖
公共无效onLoadFinished(装载机&LT;&光标GT;装载机,光标光标){
如果(cursor.isClosed()){
Log.d(TAG,游标返回CLOSED);
活动活动= getActivity();
如果(活动!= NULL){
。activity.getLoaderManager()restartLoader(mFragmentId,空,mCallbacks);
}
返回;
}
mArticleAdapter.swapCursor(光标);
} @覆盖
公共装载机&LT;&光标GT; onCreateLoader(INT ID,捆绑参数){
triggerArticleFeed();
CursorLoader cursorLoader = NULL; 如果(ID == mFragmentId){
cursorLoader =新CursorLoader(getActivity()
MyContentProvider.ARTICLES_URI,
空值,
ArticlesContentHelper.ARTICLES_WHERE,
ArticlesContentHelper.ARTICLES_WHEREARGS,
空值);
}
回报(cursorLoader);
}
};
同时实现监听器是一个非常糟糕的主意:
02-19 17:46:25.139:E / AndroidRuntime(24886):致命异常:主要
02-19 17:46:25.139:E / AndroidRuntime(24886):java.lang.IllegalStateException:已经有一个听众注册
02-19 17:46:25.139:E / AndroidRuntime(24886):在android.content.Loader.registerListener(Loader.java:152)
02-19 17:46:25.139:E / AndroidRuntime(24886):在android.app.LoaderManagerImpl $ LoaderInfo.start(LoaderManager.java:273)
02-19 17:46:25.139:E / AndroidRuntime(24886):在android.app.LoaderManagerImpl.installLoader(LoaderManager.java:523)
02-19 17:46:25.139:E / AndroidRuntime(24886):在android.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:510)
02-19 17:46:25.139:E / AndroidRuntime(24886):在android.app.LoaderManagerImpl.initLoader(LoaderManager.java:563)
所以其实这个问题的答案是:
这是必要的不可以同时实现监听。
I have an application which is using Loader
s to get at a database which is also being edited by an IntentService
. I receive data from the Loader
through a LoaderCallbacks
implementation, which is working fine.
I am also using ContentResolver#notifyChange(Uri, ContentObserver)
to trigger reload. However, this only works when I call Cursor#setNotificationUri(Uri)
beforehand.
I can find no reference to the latter method in any documentation and it seems in fact this may be causing crashes: see also
However, without this call on the Cursor
the LoaderCallbacks#onLoadFinished(Loader<Cursor>, Cursor)
is only hit after the initial load, and not after the notification. Do I also need to implement an OnLoadCompleteListener
to do, well, exactly the same thing?
ContentProvider
query method:
class MyContentProvider extends ContentProvider {
//...
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor query = db.query(getTableName(uri), projection, selection, selectionArgs, null, null, sortOrder);
query.setNotificationUri(getContext().getContentResolver(), uri);
return query;
}
//...
}
Typical LoaderCallbacks
:
LoaderCallbacks<Cursor> mCallbacks = new LoaderCallbacks<Cursor>() {
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mArticleAdapter.swapCursor(null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if(cursor.isClosed()) {
Log.d(TAG, "CURSOR RETURNED CLOSED");
Activity activity = getActivity();
if(activity!=null) {
activity.getLoaderManager().restartLoader(mFragmentId, null, mCallbacks);
}
return;
}
mArticleAdapter.swapCursor(cursor);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
triggerArticleFeed();
CursorLoader cursorLoader = null;
if(id == mFragmentId) {
cursorLoader = new CursorLoader(getActivity(),
MyContentProvider.ARTICLES_URI,
null,
ArticlesContentHelper.ARTICLES_WHERE,
ArticlesContentHelper.ARTICLES_WHEREARGS,
null);
}
return(cursorLoader);
}
};
Implementing both listeners is a very bad idea:
02-19 17:46:25.139: E/AndroidRuntime(24886): FATAL EXCEPTION: main
02-19 17:46:25.139: E/AndroidRuntime(24886): java.lang.IllegalStateException: There is already a listener registered
02-19 17:46:25.139: E/AndroidRuntime(24886): at android.content.Loader.registerListener(Loader.java:152)
02-19 17:46:25.139: E/AndroidRuntime(24886): at android.app.LoaderManagerImpl$LoaderInfo.start(LoaderManager.java:273)
02-19 17:46:25.139: E/AndroidRuntime(24886): at android.app.LoaderManagerImpl.installLoader(LoaderManager.java:523)
02-19 17:46:25.139: E/AndroidRuntime(24886): at android.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:510)
02-19 17:46:25.139: E/AndroidRuntime(24886): at android.app.LoaderManagerImpl.initLoader(LoaderManager.java:563)
So in fact the answer to this question is:
It is necessary NOT to implement both listeners.
这篇关于是否有必要同时实现LoaderCallbacks和OnLoadCompleteListener获得在ContentProvider的变化的通知?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!