Problem with AsyncTaskLoader custom callbacks

I am having a couple of problems with my AsyncTaskLoader, not sure if they are related, as they both occur when trying to restart the bootloader. In my application, I have 3 instances of a custom CursorAdapter supported by three instances of a custom AsyncTaskLoader, managed by 1 singleton LoaderManager. The problems are related to two different adapter / bootloader pairs, but the code used is the same in each case:

getLoaderManager().restartLoader(loaderId, bundle, loaderManager); 

Problem 1: I call restartLoader () and the LoaderManager registers a call to onCreateLoader, but not one for onLoaderReset (). The loader receives Result () for delivery, but onLoadFinished () is never called. The bootloader does not have the 'reset' or 'start' flags set (see code below).

Problem 2: I call restartLoader (), and the LoaderManager registers a call to onLoaderReset (). The loader gets onReset () but doesn't get any more. The cursor is set to null, but the new cursor is not loaded.

Any ideas what could be the problem? Here are some of the code for Loader and Loader Manager:

CustomCursorLoader.java

 @Override protected void onStartLoading() { Log.v(TAG, "Starting Loader"); if (lastCursor != null) { deliverResult(lastCursor); } if (takeContentChanged() || lastCursor == null) { forceLoad(); } } @Override public void deliverResult(Cursor cursor) { Log.v(TAG, "Delivering result"); if (isReset()) { Log.v(TAG, "reset"); if (cursor != null) { cursor.close(); } return; } Cursor oldCursor = lastCursor; lastCursor = cursor; if (isStarted()) { Log.v(TAG, "started"); super.deliverResult(cursor); } if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) { oldCursor.close(); } } @Override protected void onReset() { Log.v(TAG, "Reset"); super.onReset(); onStopLoading(); if (lastCursor != null && !lastCursor.isClosed()) { lastCursor.close(); } lastCursor = null; } 

CustomCursorLoaderManager.java:

 @Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) { return new CustomCursorLoader(); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { cursorAdapter.changeCursor(cursor); } @Override public void onLoaderReset(Loader<Cursor> loader) { cursorAdapter.changeCursor(null); } 
+6
source share
2 answers

What you call "LoaderManager" is actually an implementation of the LoaderManager.LoaderCallbacks<D> interface. You might want to use a different name, this is confusing. Why is this a singleton? Usually it is bound to an Activity or Fragment, perhaps only to an Activity / Fragment that implements the interface. Where do you create your loaders (activity / fragment)? Also make sure that you call LoaderManager.initLoader() from onCreate()/onActivityCreated() , otherwise the bootloader may not onCreate()/onActivityCreated() correctly.

+1
source

When you create a cursor and point it to the database, you cannot just set it to null. You must explicitly close the cursor, or it will lock the database until the time runs out.

I recommend using the Android lifecycle and existing callbacks to implement this fix.

Hope this helps!

0
source

Source: https://habr.com/ru/post/895628/


All Articles