问题
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
IllegalStateException "attempt to re-open an already-closed object" in SimpleCursorAdapter from ContentProvider
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);
}
};
回答1:
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.
来源:https://stackoverflow.com/questions/14963524/is-it-necessary-to-implement-both-loadercallbacks-and-onloadcompletelistener-to