androidandroid-fragmentsonconfigurationchangedfragmenttransaction

Multiple calls to FragmentTransaction.replace() - only one works after orientation change


I am using the following code to populate my UI with 2 fragments, the containers are FrameLayout's defined in XML. This first time this code is called i.e. when the app starts, it works fine, and both my fragments are displayed as expected. However after a configuration change(specifically, orientation), only the first fragment in the transaction is shown.

I don't think it's an issue with the fragments themselves, because if I reverse the code so one replace is called before the other or vice versa, that fragment will be displayed. So for example with the snippet from below as a guide, if I swap the mSummary and mDetails replace calls, then mDetails will be displayed and mSummary won't.

It's always the second one in the block that is missing.

// Using tablet layout
} else {
    FragmentManager fm = super.getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.replace(R.id.summary_container, mSummaryFragment);
    ft.replace(R.id.details_container, mDetailsFragment);
    ft.commit();
}

I'm saving the fragments in onSaveInstanceState and restoring them from the Bundle savedInstanceState when the activity is recreated. I also tried breaking the transaction into two pieces by calling commit() and then getting another FragmentTransaction object but no joy there.


Solution

  • So for anyone coming across this at a later stage...

    I finally manage to fix this by creating a new instance of the fragment and restoring it's state using a Fragment.SavedState object. So:

            if (mSummaryFragment.isAdded() && mDetailsFragment.isAdded()) {
                Fragment.SavedState sumState = getSupportFragmentManager().saveFragmentInstanceState(mSummaryFragment);
                Fragment.SavedState detState = getSupportFragmentManager().saveFragmentInstanceState(mDetailsFragment);
    
                mSummaryFragment = new SummaryFragment();
                mSummaryFragment.setInitialSavedState(sumState);
    
                mDetailsFragment = new DetailsFragment();
                mDetailsFragment.setInitialSavedState(detState);
            }
    
            FragmentTransaction ft = mFragmentManager.beginTransaction();
    
            ft.add(R.id.summary_container, mSummaryFragment);
            ft.add(R.id.details_container, mDetailsFragment);
    
            ft.commit();
    

    I do not understand why this works and the old method doesn't, however this may be helpful for someone else.