I noticed strange situation using Android Loaders and Fragments. When I invoke LoaderManager.initLoader() after orientation change onLoadFinished is not called (although doc
When calling initLoader
from onActivityCreated
you can detect rotation :
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState == null) {
// fresh new fragment, not orientation/config change
getLoaderManager().initLoader(YOUR_LOADER_ID, null, mCallbacks);
}
...
}
This way the loader behaves as expected resulting in single onLoadFinished
call.
It is not called on rotation anymore, so if you want loader's data, you can keep it in your fragment, for instance by overriding onSaveInstanceState
.
Edit:
I just realized that onLoadFinished
won't be called if rotation happens during loader's loadInBackground
. To fix this you'd still need to call initLoader
after rotation if the data from loader not yet available.
Hope that helps.
You can also compare the data object in onLoadFinished(Loader loader, Object data). If the data object matches one you already have, you can just not do anything when onLoadFinished is called. For example:
public void onLoadFinished(Loader loader, Object data) {
if(data != null && mData != data){
//Do something
}
}
Since all searching for this subject inevitably ends up here, I just wanted to add my experience. As @jperera said, the culprit was that LoaderManager will call onLoadFinished() if the loaders already exist. In my case, I had fragments in a FragmentPager and scrolling 2 tabs away and then scrolling next to it again would cause my old fragment to begin creating itself.
Since placing initLoader() inside onCreate() also causes double callbacks, I placed the initLoader() inside onResume(). But the sequence of events ends up being onCreate(), LoaderManager calls callbacks since loaders exist, then onResume() is called, triggering another initLoader() and onLoadFinished() sequence. IE, another double callback.
I found a quick solution by "Matt". After all your data is loaded (if you have more than one loader), destroy all of the loaders so their callbacks won't be called an extra time.
If implementing AppCompatActivity, double check you are using getSupportLoaderManager() in all cases (destroyLoader/initLoader etc). I had mistakenly used getSupportLoaderManager() in conjunction with a getLoaderManager() and suffered the same issue.