6

I have a fragment which is added programmatically. I have however discovered that after a rotation, a new fragment is created but the old fragment is still alive (though not being displayed) I assumed that fragments are destroyed along with the activity on rotation, but this is not the case here. What could be causing my fragment to be retained / not destroyed? Please note:

  1. I am not setting setRetainInstance.
  2. The fragment is not added in the activity onCreate (added later when a button is tapped)
  3. I can see onDestroy is being called for the Activity upon rotation
  4. Although the fragment is added, it obscures the add button and is only be dismissed when I do a "remove".

Code creating the fragment:

MyFragment fragment = MyFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.content_frame, fragment, "CurrentFragment");
fragmentTransaction.show(fragment).commit();

Code removing the fragment:

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(fragment).commit();

UPDATE: I cannot confirm if this was the problem, but the fragment registers as a LocalBroadcast receiver in onCreate. It unregistered for broadcasts in onDestroy, but it seems that either the LocalBroadcast registration was preventing onDestroy being called, or onDestroy was not called upon rotation. I now unregister in onStop and this seems to have solved the issue.

RunLoop
  • 20,288
  • 21
  • 96
  • 151

5 Answers5

16

When the Activity is restarted because of a orientation change, the Android Framework recreates and adds the Fragment automatically for you. You probably add the Fragment in onCreate of your Activity. That's where you add an additional Fragment after the orientation change.

You have to check if the Fragment is already added:

Fragment f = getFragmentManager().findFragmentById(R.id.content_frame);
if(f == null){
    //Add it, there is no Fragment
}else{
    //It's already there
}

Every time you tapp the button that adds the Fragment, a new Fragment will be added. If your container is a FrameLayout you probably won't see it. Try to replace the Fragments:

fragmentTransaction.replace(R.id.content_frame, fragment, "CurrentFragment");

The method setRetainInstance(true) has another purpose. If you enable it, the Fragment instance will not be destroyed when the orientation changes (but its Views will be destroyed). That means you can store data in the member variables of a Fragment and this data will still be available after an orientation change.

When setting setRetainInstance(true) the life-cycle of the Fragment is slightly different. I.e. onCreate() and onDestroy() are not called (Because those event do not happen)

thaussma
  • 9,756
  • 5
  • 44
  • 46
2

Why Cant you replace the existing fragment with new fragment which you want to load.

try this may help you.

FragmentNew mFragmentNew = new FragmentNew ();// Which you want to load That Fragment Object 
        getFragmentManager().beginTransaction()
                .replace(R.id.item_detail_container, mFragmentNew)
                .commit();
Nagaraja
  • 581
  • 1
  • 4
  • 12
2

Your fragment probably save in Bundle object before activity onDestroy(). Try to process removing fragments in onSaveInstanceState():

@Override
    protected void onSaveInstanceState(Bundle outState) {
        //remove here fragments
        super.onSaveInstanceState(outState);
    }

Or you can just make Bundle null in onCreate():

@Override
    protected void onCreate(Bundle savedInstanceState) {
        savedInstanceState = null;
        super.onCreate(savedInstanceState);
    }
ar-g
  • 3,417
  • 2
  • 28
  • 39
  • that `null` assignment would just point the copy of that handle to null. you must mean `savedInstanceState.clear()`. – homerman Jan 09 '16 at 16:35
1

I've had this issue and i solved it just Replace this line

fragmentTransaction.add(R.id.content_frame, fragment, "CurrentFragment");

To

fragmentTransaction.replace(R.id.content_frame, fragment, "CurrentFragment");

Enjoy

MFQ
  • 839
  • 8
  • 14
0

You just need to add Fragment once at first launch, do it like this: Following code is copied from http://developer.android.com/reference/android/app/Fragment.html, comment is mine:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


    // My Comment: only add when launched for the first time, it won't be null on orientation change
    if (savedInstanceState == null) {
        // During initial setup, plug in the details fragment.
        DetailsFragment details = new DetailsFragment();
        details.setArguments(getIntent().getExtras());
        getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
    }
}
M-Wajeeh
  • 17,204
  • 10
  • 66
  • 103