Do I need to implement both LoaderCallbacks and OnLoadCompleteListener to receive notification of changes in the ContentProvider?

I have an application that uses Loader to get into a database, which is also edited by IntentService . I get data from the Loader implementation through LoaderCallbacks , which works fine.

I also use ContentResolver#notifyChange(Uri, ContentObserver) to trigger a reboot. However, this works when I call Cursor#setNotificationUri(Uri) in advance.

I can’t find a link to the last method in any documentation, and it seems like this could lead to crashes: see also

IllegalStateException "trying to reopen an already closed object" in SimpleCursorAdapter from ContentProvider

However, without this call to Cursor , LoaderCallbacks#onLoadFinished(Loader<Cursor>, Cursor) gets only after the boot, and not after notification. Do I need to also implement OnLoadCompleteListener , well, exactly the same?

ContentProvider request 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); } }; 
0
source share
1 answer

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 the answer to this question is actually:

For the implementation of both listeners, it is NOT necessary.

+1
source

All Articles