Fragment常見的兩種重建方式,一種是經過調用setRetainInstance
來通知系統在重建Activity(例如屏幕配置改變)時保留此Fragment;另外一種方式是系統在重建Activity時自動重建Fragment,典型例子是FragmentActivity對管理的Fragment的重建。android
直接參考官方文檔的解釋: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
調用了此方法後,Activity被銷燬時,此Fragment會被保留(進程不消亡的前提下),Activity重建時,Fragment直接掛載。ide
原理:當配置發生變化時,Activity進入銷燬過程,FragmentManager先銷燬隊列中Fragment的視圖,而後檢查每一個Fragment的retainInstance屬性。若是retainInstance爲false,FragmentManager會銷燬該Fragment實例;若是retainInstance爲true,則不會銷燬該Fragment實例,Activity重建後,新的FragmentManager會找到保留的Fragment併爲其建立視圖。spa
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。