11

I have a support library fragment that sends a network call, and recreate() the parent activity when it receives a specific network response. I can see that the activity does get recreated as I can see the onCreate() and onDestroy() are called.

But after the activity is recreated, the fragment is still there and it got stuck in a loop which keep recreating and making new fragments.

Here's part of the onCreate() of the activity:

    if (someLogic()) {
        fragmentA = new FragmentA();
        FragmentUtil.addFragment(getSupportFragmentManager(), fragmentA);
    } else {
        fragmentB = new FragmentB();
        FragmentUtil.addFragment(getSupportFragmentManager(), fragmentB);
    }

FragmentA is the one that does the network call, and FragmentB is the fragment that should be displayed after the recreate(). When I check the list of fragments with getSupportFragmentManager().getFragments() I see 1 instances of FragmentA, and 16 instances of FragmentB.

My question is why does this happen, and how do I fix it?

Cash Lo
  • 1,052
  • 1
  • 8
  • 20
  • Can you show how you add the fragments and recreate the activity? My guess is that you have to remove fragmentA before restarting the activity but I would need to see the code. Btw why don't you simply replace fragmentA with fragmentB instead of restarting the activity? – Pasquale Anatriello Nov 10 '14 at 18:00
  • Not that it is a concrete answer or that it is the ideal solution but you could check your fragment stack and only add a new fragment if you need to, else/or you could replace/refresh the current fragment – zgc7009 Nov 10 '14 at 18:03

2 Answers2

19

Calling recreate() essentially causes the Activity to go through a configuration change. A configuration change causes both the Activity and its Fragments to be destroyed and recreated. So your Fragments should in fact be destroyed when this occurs (you can see for yourself by adding a Log message in your fragment's onDestroy method).

The fact that configuration changes cause fragments to be destroyed and created however does not mean that the FragmentManager will simply forget the fragments ever existed. The FragmentManager will still hold a reference to the newly created fragment after the configuration change occurs.

One thing you can do to prevent multiple fragments from being created is by doing something like this in your activity's onCreate():

if (savedInstanceState == null) {
    // The Activity is being created for the first time, so create and
    // add new fragments.
} else {
    // Otherwise, the activity is coming back after being destroyed.
    // The FragmentManager will restore the old Fragments so we don't
    // need to create any new ones here.
}
Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
  • 8
    anyway to explicitly not retain a fragment during recreation? I have a day/night mode layout setup and i've having some issues multiple copies of the fragment in memory – spy Apr 10 '16 at 03:05
  • 1
    @spy you can remove the fragment manually before recreating the Activity, "mFragmentManager.beginTransaction().remove(mFragment).commit();". – Xiaozou Oct 21 '16 at 08:57
8

I had same situation as @spy wrote, recreating the Activity after Day/Night mode is changed. Activity had four Fragments which they get restored after Activity.recreate() is called, because FragmentManager saves them as @Alex Lockwood stated. But restoring and not adding Fragments after recreation does not help me because of some architectural reasons of project, i wanted them to disappear.

Solution is to delete Fragments from FragmentManager just before Activity.recreate()is called, in my case it is in Activity.onStart():

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

Fragment fragmentA = fragmentManager.findFragmentByTag("fragmentATag");
if(fragmentA != null) 
    fragmentTransaction.remove(fragment);
// Find and delete other Fragments

fragmentTransaction.commit(); // or commitAllowingStateLoss()

recreate();

This way you will not get Fragments restored when Activity.onCreate() is called.

Jemshit
  • 9,501
  • 5
  • 69
  • 106
  • 1
    another option is to call `super.onCreate(null);` on activity creation, however, I am not sure what other drawbacks it may have – Javanshir May 04 '18 at 11:41