There are two common ways to rebuild a Fragment. One is to call setRetainInstance to tell the system to keep the Fragment while rebuilding an Activity(such as a screen configuration change). Another way is for the system to automatically rebuild a Fragment when rebuilding an Activity. A typical example is the FragmentActivity rebuilding a managed Fragment.

setRetainInstance

Refer directly to the official documentation for explanation:

Control whether a fragment instance is retained across Activity re-creation (such as from a configuration change). This can only be used with fragments not in the back stack. If set, the fragment lifecycle will be slightly different when an activity is recreated:

  • onDestroy() will not be called (but onDetach() still will be, because the fragment is being detached from its current activity).
  • onCreate(android.os.Bundle) will not be called since the fragment is not being re-created.
  • onAttach(android.app.Activity) and onActivityCreated(android.os.Bundle) will still be called.

After this method is called, the Fragment is retained when the Activity is destroyed (as long as the process does not die) and mounted directly when the Activity is rebuilt.

Principle: When a configuration change occurs, the FragmentManager destroys the Fragment view in the queue and then checks the retainInstance property of each Fragment. If retainInstance is false, the FragmentManager destroys the Fragment instance. If retainInstance is true, the Fragment instance is not destroyed, and after the Activity is rebuilt, the new FragmentManager finds the remaining Fragment and creates a view for it.

FragmentActivity Rebuilds the Fragment

When a FragmentActivity’s configuration change is destroyed, the Fragment state in the FragmentManager is saved, and the destroyed Fragment is rebuilt later when the Activity rebuilds. In this case, instead of creating a new Fragment in onCreate, the Activity rebuilds using the Fragment that was automatically rebuilt (which can be found by tag). The Fragment state saving and rebuilding process can be viewed in the FragmentActivity code.

When the configuration changes and the Activity is about to be destroyed, the FragmentActivity first stores the Fragment state of all queues.

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        markFragmentsCreated();
        Parcelable p = mFragments.saveAllState();
        if(p ! = null) { outState.putParcelable(FRAGMENTS_TAG, p); }Copy the code

MFragments for reference, FragmentManager FragmentManager. SaveAllState returns a contains need to keep the fragments of the Parcelable, this data will be used for reconstruction after these fragments.

See FragmentManager saveAllState method implementation, you can see the returned Parcelable for an actual FragmentManagerState instance, the class data member is defined as:

final class FragmentManagerState implements Parcelable {
    FragmentState[] mActive;
    int[] mAdded;
    BackStackState[] mBackStack;
    int mPrimaryNavActiveIndex = -1;
    int mNextFragmentIndex;
}
Copy the code

FragmentState data member:

final class FragmentState implements Parcelable {
    final String mClassName;
    final int mIndex;
    final boolean mFromLayout;
    final int mFragmentId;
    final int mContainerId;
    final String mTag;
    final boolean mRetainInstance;
    final boolean mDetached;
    final Bundle mArguments;
    final boolean mHidden;

    Bundle mSavedFragmentState;

    Fragment mInstance;
}
Copy the code

FragmentState contains the various data variables that describe the Fragment, enough to recreate a destroyed Fragment from zero.

After saving the Fragment data, both the Activity instance and the Fragment instance that did not call setRetainInstance(True) are destroyed.

When the Activity is rebuilt, the Fragment that was destroyed is also rebuilt:

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);

        super.onCreate(savedInstanceState);

        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if(nc ! = null) { mViewModelStore = nc.viewModelStore; }if(savedInstanceState ! = null) { Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG); mFragments.restoreAllState(p, nc ! = null ? nc.fragments : null);Copy the code

The FragmentActivity recreates the Fragment that was previously saved and destroyed by calling the restoreAllState method of the FragmentManager.