I am using the LoaderManager to handle a query that is backing a listview. It relies on some parameters that aren't known until later in the process though. Currently I call
getSupportLoaderManager().initLoader(0, null, callback);
within onCreate(). This will immediately create the loader and execute the query, before the parameters are all known. To handle that, I have a dummy query in onCreateLoader() when not all params are known, and a flag in my callback handler that checks within onLoadFinished() whether or not we have a legitimate query. If it's not, I ignore the cursor data. When it comes time to do a real query, I call
getSupportLoaderManager().restartLoader(0, null, callback);
and also set my flag to true, so that onLoadFinshed() handles it properly.
What I'm doing above seems kind of hacky; is there a better way? I originally tried to call initLoader() later, when I first need the query, but then things fail upon orientation changes, similar to this question.
SELECT * from sqlite_master LIMIT 0
- thanks matt ;) ) or you have a CursorLoader subclass like EmptyCursorLoader that covers this for yo - Dori 2012-07-10 14:08
Just to close the question, for my use case I was able to rely on using the per-fragment loader managers, instantiating those when I needed them and had the info. If this doesn't fit anyone else's use case, perhaps my original hack is good enough, if you want to avoid writing AsyncTasks and take advantage of some of the built-in functionality of a loader.
You can simply call restartLoader
without calling initLoader
first. Just remove the initLoader
call from onCreate
, and run restartLoader
once you have your params, no flag needed.
I found another, much simpler solution. For some reason you have to call initLoader() in your onCreate(), but because you have to pass LoaderCallbacks every time you call restartLoader() it doesn't really matter, what callbacks you use in this first, dummy call to initLoader(). I have created very simple utility methods:
public static void initEmptyLoaders(Activity activity, int... ids) {
initEmptyLoaders(activity, activity.getLoaderManager(), ids);
}
public static void initEmptyLoaders(final Context ctx, LoaderManager loaderManager, int... ids) {
LoaderManager.LoaderCallbacks callbacks = new LoaderManager.LoaderCallbacks() {
@Override
public Loader onCreateLoader(int i, Bundle bundle) {
return new Loader(ctx);
}
@Override
public void onLoadFinished(Loader loader, Object o) {
}
@Override
public void onLoaderReset(Loader loader) {
}
};
for (int id : ids) {
loaderManager.initLoader(id, null, callbacks);
}
}
Now I call initEmptyLoaders() in my onCreate() with every loader id I may need later - everything works :-)
This is an old issue than still exist in some androids, and the support libraries are more updated. Then use the android.support.v4.*
version of the Loader API to fix it.
Loader
. Use something else to move the work to the background, likeAsyncTask
- CommonsWare 2012-04-04 22:13