savedInstanceState when restoring fragment from back stack

56,794

Solution 1

onSaveInstanceState is (unfortunately) not called in normal back-stack re-creation of a fragment. Check out http://developer.android.com/guide/components/fragments.html#Creating and the answer on How can I maintain fragment state when added to the back stack?

Solution 2

I like to store the View I return in onCreateView as a global variable and then when I return I simply check this:

if(mBaseView != null) {
        // Remove the view from the parent
        ((ViewGroup)mBaseView.getParent()).removeView(mBaseView);
        // Return it
        return mBaseView;
    }

Solution 3

The problem is that the fragment needs to have an Id or Tag associated with it in order for the FragmentManager to keep track of it.

There are at least 3 ways to do this:

  1. In xml layout declare an Id for your fragment:

    android:id=@+id/<Id>
    
  2. If your fragments container View has an Id, use FragmentTransaction:

    FragmentTransaction  add (int containerViewId, Fragment fragment)
    
  3. If your fragment is not associated with any View (e.g. headless fragment), give it a Tag:

    FragmentTransaction  add (Fragment fragment, String tag)
    

Also, see this SO answer.

Share:
56,794
heero
Author by

heero

Updated on July 18, 2020

Comments

  • heero
    heero almost 4 years

    Can I use savedInstanceState() to save the state when removing a fragment, then restore the state when I pop the fragment off the back stack? When I restore the fragment from the back stack, savedInstanceState bundle is always null.

    Right now, the app flow is: fragment created -> fragment removed (added to back stack) -> fragment restored from back stack (savedInstanceState bundle is null).

    Here is the relevant code:

    public void onActivityCreated(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        Long playlistId = bundle.getLong(Constants.PLAYLIST_ID);
        int playlistItemId = bundle.getInt(Constants.PLAYLISTITEM_ID);
    
        if (savedInstanceState == null) {
           selectedVideoNumber = playlistItemId;
        } else {
           selectedVideoNumber = savedInstanceState.getInt("SELECTED_VIDEO");
        }
    }
    
    public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putInt(Constants.SELECTED_VIDEO, selectedVideoNumber);
        }
    

    I think the problem is that onSavedInstanceState() is never called when being removed and being added to back stack. If I cant use onsavedInstanceState(), is there another way to fix this?

  • craigrs84
    craigrs84 about 10 years
    not sure this is a good idea. Does this defeat the purpose of destroying the view to free memory if you save a reference to it?
  • AllDayAmazing
    AllDayAmazing about 10 years
    I'm actually not sure, as I haven't run any direct tests. However, my thinking goes like this. When you initialize all the elements in your layout, it's standard to set most of those elements as a global variables, so if in the above example I couldn't recycle the base View because of the reference, Android wouldn't be able to recycle any of these Views either, thus leading to the same issue with memory.
  • bcorso
    bcorso almost 10 years
    This won't work if you need different views to be inflated for different orientations.
  • brainmurphy1
    brainmurphy1 almost 10 years
    This solution saved my life.