Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting "Called doStart when already started" from LoaderManager. Why?

My code has an Activity, that has a FragmentPagerAdapter that creates 'n' fragments as necessary. Activity has a loader, and each fragment has its own loader. All loaders have unique ID. (Activity's loader in fact determines the number of Pages in the adapter)

I keep getting this warning here and there and can't put my finger on what's causing it. It doesn't seem to be critical, also looking at the LoaderManger's code throwing this warning, but still - warnings are usually signs for bugs..

Had originally used FragmentStatePagerAdapter and then moved to FragmentPagerAdapter, thinking that could somehow be the issue - but obviously it's not.

Posting code would really complicate this and add very little.

Any thoughts?

like image 472
JRun Avatar asked Jan 28 '13 10:01

JRun


2 Answers

in your fragment move your initLoader method inside the onActivityCreated method.

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onActivityCreated(savedInstanceState);

    LoaderManager lm = getLoaderManager();
    lm.initLoader(LOADER_ID, null, this);
}
like image 188
mina Avatar answered Oct 25 '22 10:10

mina


I've just finished a few hours long debugging session with the support library.

TL;DR: DO NOT CALL getLoaderManager in Fragment.onCreate, use onActivityCreated!
(this implies that you can't do initLoader before onActivityCreated)

Fragment.getLoaderManager() will lazily get a LoaderManager instance for you from the activity. However for this to be a valid one the fragment already has to be activated (FragmentManager.makeActive), which implies two things relevant here:

  • the Fragment has been added
    (FragmentManager.addFragment)
  • the Fragment has an internal identifier (mWho)
    (makeActive calls Fragment.setIndex)

The latter is really important because when you call Fragment.getLoaderManager() which in turn asks FragmentActivity.getLoaderManager(who, ...) for a real manager. When called from Fragment.onCreate() the makeActive call didn't happen yet so you'll get back a LoaderManagerImpl with mWho == null which is bad, because the framework will reassign the LoaderManager instance to every fragment which has similar lifecycle.

Because of this reassignment the LoaderManager has already been started by one fragment, but another one will try to start it as well, because the activity didn't know which fragment is asking, neither of them had their identity (mWho) yet.

like image 28
TWiStErRob Avatar answered Oct 25 '22 08:10

TWiStErRob