I noticed strange situation using Android Loaders and Fragments. When I invoke LoaderManager.initLoader() after orientation change onLoadFinished is not called (although documentation suggests I should be prepared for this) but it is called twice after this. Here is link to post in google groups which describe the same situation https://groups.google.com/forum/?fromgroups#!topic/android-developers/aA2vHYxSskU . I wrote sample application in which I only init simple Loader in Fragment.onActivityCreated() to check if this happens and it does. Anyone noticed this?
You can put the initLoader() method inside your Fragment's onResume() callback; then the Loader's onLoadFinished() will not be called twice anymore.
@Override
public void onResume()
{
super.onResume();
getLoaderManager().initLoader(0, null, this);
}
This problem manifested itself for me with a CursorLoader returning a Cursor that was already closed:
android.database.StaleDataException: Attempted to access a cursor after it has been closed.
I'd guess this is a bug or an oversight. While moving initLoader() into onResume may work, what I was able to do was remove the Loader when I'm done with it:
To start the loader (in my onCreate):
getLoaderManager().initLoader(MUSIC_LOADER_ID, null, this);
Then after I'm done with it (basically at the end of onLoadFinished)
getLoaderManager().destroyLoader(MUSIC_LOADER_ID);
This seems to behave as expected, no extra calls.
initLoader documentation says,
If at the point of call the caller is in its started state, and the requested loader already exists and has generated its data, then callback onLoadFinished(Loader, D)
I suggest you to implement something like onStartLoading function at this sample
For quick test you can try:
@Override protected void onStartLoading() {
forceLoad();
}
This launch loadInBackground function and then onLoadFinished in Fragment.
Any way, if you attach some code i'll try to give you more help.
I solved the problem of onLoadFinished being called twice like this. In your Fragment.onActivityCreated() init your Loader like this
if (getLoaderManager().getLoader(LOADER_ID) == null) {
getLoaderManager().initLoader(LOADER_ID, bundle, loaderCallbacks);
} else {
getLoaderManager().restartLoader(LOADER_ID, bundle, loaderCallbacks);
}
here loaderCallbacks implements your usual Loader callbacks
private LoaderManager.LoaderCallbacks<T> loaderCallbacks
= new LoaderManager.LoaderCallbacks<T>() {
@Override
public Loader<T> onCreateLoader(int id, Bundle args) {
...
...
}
@Override
public void onLoadFinished(Loader<T> loader, T data) {
...
...
}
@Override
public void onLoaderReset(Loader<T> loader) {
...
...
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With