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

2

7

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?

Hello answered 28/1, 2013 at 10:2 Comment(0)
M
15

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);
}
Manufacturer answered 31/1, 2013 at 18:15 Comment(5)
Thanks! Works like a charm, and seems like a no-brainer now that I have your answer staring at me :-) Thank you.Hello
you are welcome, and if you switched to FragmentPagerAdapter because this problem, it should works too with the FragmentStatePagerAdapterManufacturer
This did not help in my case, I still keep getting this exception when I attach / deattach to a fragment that inits a loader on onActivityCreated a couple times.Blaise
What is most imperative in answer is that getLoader must be called in onActivityCreated, if you call it before then, I was still seeing issues even tho I called init in onActivityCreatedWellborn
as explained by Google's Android class on Udacity: "Loaders are initialized in onActivityCreated because their lifecycle is actually bound to the Activity, not the Fragment", which explains why @Manufacturer 's answer is correct.Vagrant
S
4

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.

Sopher answered 15/3, 2015 at 1:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.