Android 中Fragment的自动重建

Fragment常见的两种重建方式,一种是经过调用setRetainInstance来通知系统在重建Activity(例如屏幕配置改变)时保留此Fragment;另外一种方式是系统在重建Activity时自动重建Fragment,典型例子是FragmentActivity对管理的Fragment的重建。android

setRetainInstance

直接参考官方文档的解释:bash

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:app

  • 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.

调用了此方法后,Activity被销毁时,此Fragment会被保留(进程不消亡的前提下),Activity重建时,Fragment直接挂载。ide

原理:当配置发生变化时,Activity进入销毁过程,FragmentManager先销毁队列中Fragment的视图,而后检查每一个Fragment的retainInstance属性。若是retainInstance为false,FragmentManager会销毁该Fragment实例;若是retainInstance为true,则不会销毁该Fragment实例,Activity重建后,新的FragmentManager会找到保留的Fragment并为其建立视图。spa

FragmentActivity对Fragment的重建

FragmentActivity在配置改变被销毁时,FragmentManager中的Fragment状态会被保存下来,等以后Activity重建时,被销毁的Fragment也会被重建。因此在这种状况下,Activity重建时,不须要再在onCreate中建立新的Fragment,而是使用被自动重建的Fragment(能够经过tag找到)。Fragment的状态保存及重建过程能够在FragmentActivity的代码中查看。rest

当配置改变,Activity即将销毁时,FragmentActivity会先保存全部队列中的Fragment状态。code

@Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        markFragmentsCreated();
        Parcelable p = mFragments.saveAllState();
        if (p != null) {
            outState.putParcelable(FRAGMENTS_TAG, p);
        }
复制代码

mFragments为FragmentManager的引用,FragmentManager.saveAllState返回一个包含须要保存的Fragment的Parcelable,此数据以后会用于重建这些Fragment。队列

查看FragmentManager.saveAllState方法的实现,能够看出返回的Parcelable实际为一个FragmentManagerState实例,该类的数据成员定义为:进程

final class FragmentManagerState implements Parcelable {
    FragmentState[] mActive;
    int[] mAdded;
    BackStackState[] mBackStack;
    int mPrimaryNavActiveIndex = -1;
    int mNextFragmentIndex;
}
复制代码

FragmentState的数据成员:文档

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;
}
复制代码

FragmentState包含描述Fragment的各个数据变量,足够从零从新建立一个被销毁的Fragment。

在保存了Fragment数据以后,Activity实例以及没有调用setRetainInstance(true)的Fragment实例都被销毁。

而当Activity重建时,被销毁的Fragment也会被重建:

@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);
复制代码

FragmentActivity经过调用FragmentManager的restoreAllState方法,重建以前保存下来并被销毁的Fragment。

相关文章
相关标签/搜索