Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preferred method of loading dependent queries with LoaderManager

What is the preferred method of loading dependant queries with the LoaderManager API in Android? As of now the best I could come up with is something along the lines of:

@Override
public void onCreate( Bundle savedInstanceState ) {
    getLoaderManager().initLoader( FIRST, null, this );
}

@Override
public void onLoadFinished( Loader<Cursor> loader, Cursor data ) {
    switch ( loader.getId() ) {
    case FIRST:
        Bundle args = new Bundle();
        args.putInt( ID, somethingFromData( data ) );
        getLoaderManager().restartLoader( SECOND, args, this );
        break;

    case SECOND:
        somethingElseFromData( data );
        break;
    }
}

This works fine most of the time, but it crashes horribly under one special case. Say I launch a second activity or push a fragment on top of this that modifies the data of FIRST. Now when I navigate back to the activity/fragment with the code above it first refreshes me with the old data of FIRST and SECOND, and since FIRST initiates SECOND, SECOND is reloaded with the new data. Now since FIRST is changed it is loaded again, which causes yet another load of SECOND to initiate.

First of all if you count that that sums up to two loads of FIRST (one old and one new) and three loads of SECOND (two old and one new), which seams at least a bit wasteful. I don't really mind that, except it is a hassle to debug, but it also seems to me to behave non-deterministically, because you don't know which loads will finish first. Will I end up with the new data for SECOND if the relation between FIRST and SECOND changed, or will I end up with the cached values?

I know that I can mitigate this by keeping score of when to restart the second loader, but there has to be a better way of doing this.

To clarify a bit: The problem is most prominent if rows in FIRST contains a reference to rows in SECOND and after the back navigation the row(s) in FIRST loaded does not point to the same row(s) in SECOND as before.

like image 361
Andreas Hagen Avatar asked Aug 06 '15 04:08

Andreas Hagen


People also ask

How can we use loaders to display and load data?

There is only one LoaderManager per activity or fragment, but a LoaderManager can manage multiple loaders. To get LoaderManager, call getSupportLoaderManager() from the activity or fragment. To start loading data from a loader, call either initLoader() or restartLoader() .

What is cursor loader?

A CursorLoader is a specialized member of Android's loader framework specifically designed to handle cursors. In a typical implementation, a CursorLoader uses a ContentProvider to run a query against a database, then returns the cursor produced from the ContentProvider back to an activity or fragment.

What is use of loader in Android?

Loaders are special purpose classes that manage loading and reloading updated data asynchronously in the background using AsyncTask. Introduced in Android 3.0, loaders have these characteristics: They are available to every Activity and Fragment. They provide asynchronous loading of data in the background.


1 Answers

Given that the only thing your first loader does is effectively prepare arguments for your second loader, you should subclass your own AsyncTaskLoader and do the whole operation within one loader.

This article contains a very in-depth example of a custom AsyncTaskLoader, which I'm sure you could adapt to your own needs. You also should look at the CursorLoader source code for a better grasp of how to write your own.

like image 185
JoeyJubb Avatar answered Sep 19 '22 14:09

JoeyJubb