Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble with Custom AsyncTaskLoader callbacks

I'm having a couple of problems with my AsyncTaskLoader, not sure if they're related as they both happen when attempting to restart the Loader. In my application I have 3 instances of a custom CursorAdapter, backed by 3 instances of a custom AsyncTaskLoader managed by 1 singleton LoaderManager. The problems relate to two differenct Adapter/Loader 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 to onLoaderReset(). The Loader gets to deliverResult(), but onLoadFinished() is never called. The Loader has neither the 'reset' or 'started' flags set (see code below).

Problem 2: I call restartLoader() and the LoaderManager registers a call to onLoaderReset(). The Loader gets to onReset(), but doesn't get any further. The Cursor is set to null, but no new Cursor is loaded.

Any ideas what the problem could be? Here's some of the code for the 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);
}
like image 695
Pikaling Avatar asked Aug 22 '11 20:08

Pikaling


1 Answers

What you are calling a 'LoaderManager' is actually an implementation of the LoaderManager.LoaderCallbacks<D> interface. You might want to use a different name, this one is confusing. Why is it a singleton? It usually is tied to an Activity or Fragment, possibly just the Activity/Fragment implementing the interface. Where are you creating your Loaders (activity/fragment)? Also make sure you call LoaderManager.initLoader() from onCreate()/onActivityCreated(), otherwise the loader may not be started properly.

like image 65
Nikolay Elenkov Avatar answered Oct 23 '22 07:10

Nikolay Elenkov