我们知道Activity提供了onSaveInstanceState和onRestoreInstanceState回调方法用于状态保存和恢复,同样FragmentActivity和Fragment也支持状态保存和恢复,FragmentActivity会在适当的时机,通过FragmentManagerImpl通知Fragment进行保存操作,接下来从源码中跟踪这个通知过程。
文中源码基于’androidx.fragment:fragment:1.1.0’
FragmentActivity重写了onSaveInstanceState方法:
[FragmentActivity.java]
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
// ···
// 调用FragmentController的saveAllState方法获取Parcelable
Parcelable p = mFragments.saveAllState();
if (p != null) {
// 将Parcelable保存进outState,FRAGMENTS_TAG值为"android:support:fragments"
outState.putParcelable(FRAGMENTS_TAG, p);
}
// ···
}
outState中以FRAGMENTS_TAG为key存储数据。
FragmentController的saveAllState方法中又调用FragmentManagerImpl的saveAllState方法:
[FragmentManagerImpl.java]
Parcelable saveAllState() {
// Make sure all pending operations have now been executed to get
// our state update-to-date.
forcePostponedTransactions();
endAnimatingAwayFragments();
execPendingActions();
// 标记状态保存为true
mStateSaved = true;
if (mActive.isEmpty()) {
return null;
}
// First collect all active fragments.
int size = mActive.size();
ArrayList<FragmentState> active = new ArrayList<>(size);
boolean haveFragments = false;
for (Fragment f : mActive.values()) {
if (f != null) {
if (f.mFragmentManager != this) {
throwException(new IllegalStateException(
"Failure saving state: active " + f
+ " was removed from the FragmentManager"));
}
haveFragments = true;
// 创建FragmentState用于保存Fragment中的成员变量值
FragmentState fs = new FragmentState(f);
active.add(fs);
// fs.mSavedFragmentState此时默认为空
if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
// 派发通知fragment进行数据保存
fs.mSavedFragmentState = saveFragmentBasicState(f);
// 若有setTargetFragment,则进行TargetFragment相关数据保存
if (f.mTargetWho != null) {
Fragment target = mActive.get(f.mTargetWho);
if (target == null) {
throwException(new IllegalStateException(
"Failure saving state: " + f
+ " has target not in fragment manager: "
+ f.mTargetWho));
}
if (fs.mSavedFragmentState == null) {
fs.mSavedFragmentState = new Bundle();
}
putFragment(fs.mSavedFragmentState,
FragmentManagerImpl.TARGET_STATE_TAG, target);
if (f.mTargetRequestCode != 0) {
fs.mSavedFragmentState.putInt(
FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
f.mTargetRequestCode);
}
}
} else {
fs.mSavedFragmentState = f.mSavedFragmentState;
}
if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
+ fs.mSavedFragmentState);
}
}
if (!haveFragments) {
if (DEBUG) Log.v(TAG, "saveAllState: no fragments!");
return null;
}
ArrayList<String> added = null;
BackStackState[] backStack = null;
// Build list of currently added fragments.
// 保存mAdded集合中的Fragment唯一ID
size = mAdded.size();
if (size > 0) {
added = new ArrayList<>(size);
for (Fragment f : mAdded) {
// f.mWho为Fragment实例化时生成的唯一UUID
added.add(f.mWho);
if (f.mFragmentManager != this) {
throwException(new IllegalStateException(
"Failure saving state: active " + f
+ " was removed from the FragmentManager"));
}
if (DEBUG) {
Log.v(TAG, "saveAllState: adding fragment (" + f.mWho
+ "): " + f);
}
}
}
// Now save back stack.
// 若有addToBackStack,则进行回退栈相关数据保存
if (mBackStack != null) {
size = mBackStack.size();
if (size > 0) {
backStack = new BackStackState[size];
for (int i = 0; i < size; i++) {
// 创建BackStackState用于保存BackStackRecord的数据
backStack[i] = new BackStackState(mBackStack.get(i));
if (DEBUG) Log.v(TAG, "saveAllState: adding back stack #" + i
+ ": " + mBackStack.get(i));
}
}
}
// 创建FragmentManagerState用于保存该FragmentManagerImpl整体数据
FragmentManagerState fms = new FragmentManagerState();
fms.mActive = active;
fms.mAdded = added;
fms.mBackStack = backStack;
if (mPrimaryNav != null) {
fms.mPrimaryNavActiveWho = mPrimaryNav.mWho;
}
fms.mNextFragmentIndex = mNextFragmentIndex;
return fms;
}
该方法中创建FragmentState集合用以保存每个Fragment的数据,String集合保存每个Fragment的唯一ID,BackStackState数组保存每个BackStackRecord的数据,最终创建FragmentManagerState用以保存以上所有数据,并返回添加进Bundle中。
接着看saveFragmentBasicState方法,该方法中进行更详细的数据保存,返回Bundle赋值给FragmentState的mSavedFragmentState成员保存:
[FragmentManagerImpl.java]
Bundle saveFragmentBasicState(Fragment f) {
Bundle result = null;
if (mStateBundle == null) {
mStateBundle = new Bundle();
}
// 触发Fragment的onSaveInstanceState回调方法;通知Fragment的子Fragment进行状态保存
f.performSaveInstanceState(mStateBundle);
// Lifecycle架构组件回调通知
dispatchOnFragmentSaveInstanceState(f, mStateBundle, false);
if (!mStateBundle.isEmpty()) {
result = mStateBundle;
mStateBundle = null;
}
// 若该fragment设置了view,则进行相关视图树的保存
if (f.mView != null) {
saveFragmentViewState(f);
}
if (f.mSavedViewState != null) {
if (result == null) {
result = new Bundle();
}
// 添加视图树数据
result.putSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
}
if (!f.mUserVisibleHint) {
if (result == null) {
result = new Bundle();
}
// Only add this if it's not the default value
// 不可见时保存mUserVisibleHint
result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
}
return result;
}
该方法中会通过performSaveInstanceState方法触发Fragment的onSaveInstanceState回调方法,Fragment子类可重写该方法保存数据。若该Fragment有设置view,还将通过Fragment的mInnerView成员的saveHierarchyState方法进行视图树的保存。
在进行了这一系列的保存后,数据都整合添加进Bundle,由ActivityClientRecord的state成员保存,同时FragmentManagerImpl的mStateSaved被标记为true。
进入FragmentActivity的onCreate方法:
[FragmentActivity.java]
protected void onCreate(@Nullable Bundle savedInstanceState) {
mFragments.attachHost(null /*parent*/);
if (savedInstanceState != null) {
// 当savedInstanceState不为空时,取出FRAGMENTS_TAG对应的数据
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
// 将数据交给FragmentManagerImpl进行状态恢复
mFragments.restoreSaveState(p);
// Check if there are any pending onActivityResult calls to descendent Fragments.
if (savedInstanceState.containsKey(NEXT_CANDIDATE_REQUEST_INDEX_TAG)) {
mNextCandidateRequestIndex =
savedInstanceState.getInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG);
int[] requestCodes = savedInstanceState.getIntArray(ALLOCATED_REQUEST_INDICIES_TAG);
String[] fragmentWhos = savedInstanceState.getStringArray(REQUEST_FRAGMENT_WHO_TAG);
if (requestCodes == null || fragmentWhos == null ||
requestCodes.length != fragmentWhos.length) {
Log.w(TAG, "Invalid requestCode mapping in savedInstanceState.");
} else {
mPendingFragmentActivityResults = new SparseArrayCompat<>(requestCodes.length);
for (int i = 0; i < requestCodes.length; i++) {
mPendingFragmentActivityResults.put(requestCodes[i], fragmentWhos[i]);
}
}
}
}
if (mPendingFragmentActivityResults == null) {
mPendingFragmentActivityResults = new SparseArrayCompat<>();
mNextCandidateRequestIndex = 0;
}
super.onCreate(savedInstanceState);
mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
mFragments.dispatchCreate();
}
在onCreate中,若savedInstanceState不为空,则取出FRAGMENTS_TAG对应的数据,通过FragmentManagerImpl的restoreSaveState方法进行状态恢复。
接着看restoreSaveState方法:
[FragmentManagerImpl.java]
void restoreSaveState(Parcelable state) {
// If there is no saved state at all, then there's nothing else to do
if (state == null) return;
FragmentManagerState fms = (FragmentManagerState)state;
if (fms.mActive == null) return;
// First re-attach any non-config instances we are retaining back
// to their saved state, so we don't try to instantiate them again.
// 处理setRetainInstance相关的Fragment的状态恢复
for (Fragment f : mNonConfig.getRetainedFragments()) {
if (DEBUG) Log.v(TAG, "restoreSaveState: re-attaching retained " + f);
FragmentState fs = null;
for (FragmentState fragmentState : fms.mActive) {
if (fragmentState.mWho.equals(f.mWho)) {
fs = fragmentState;
break;
}
}
if (fs == null) {
// 若RetainedFragment对应的RetainedFragment不存在,则需要移除该RetainedFragment
if (DEBUG) {
Log.v(TAG, "Discarding retained Fragment " + f
+ " that was not found in the set of active Fragments " + fms.mActive);
}
// We need to ensure that onDestroy and any other clean up is done
// so move the Fragment up to CREATED, then mark it as being removed, then
// destroy it.
moveToState(f, Fragment.CREATED, 0, 0, false);
f.mRemoving = true;
moveToState(f, Fragment.INITIALIZING, 0, 0, false);
continue;
}
fs.mInstance = f;
f.mSavedViewState = null;
f.mBackStackNesting = 0;
f.mInLayout = false;
f.mAdded = false;
f.mTargetWho = f.mTarget != null ? f.mTarget.mWho : null;
f.mTarget = null;
if (fs.mSavedFragmentState != null) {
// 恢复RetainedFragment的数据
fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG);
f.mSavedFragmentState = fs.mSavedFragmentState;
}
}
// Build the full list of active fragments, instantiating them from
// their saved state.
mActive.clear();
for (FragmentState fs : fms.mActive) {
if (fs != null) {
// 实例化Fragment,并用FragmentState保存的数据来初始化Fragment
Fragment f = fs.instantiate(mHost.getContext().getClassLoader(),
getFragmentFactory());
f.mFragmentManager = this;
if (DEBUG) Log.v(TAG, "restoreSaveState: active (" + f.mWho + "): " + f);
// 添加fragment至mActive成员中
mActive.put(f.mWho, f);
// Now that the fragment is instantiated (or came from being
// retained above), clear mInstance in case we end up re-restoring
// from this FragmentState again.
fs.mInstance = null;
}
}
// Build the list of currently added fragments.
mAdded.clear();
if (fms.mAdded != null) {
for (String who : fms.mAdded) {
// 获取前面刚刚创建并保存的fragment
Fragment f = mActive.get(who);
if (f == null) {
throwException(new IllegalStateException(
"No instantiated fragment for (" + who + ")"));
}
f.mAdded = true;
if (DEBUG) Log.v(TAG, "restoreSaveState: added (" + who + "): " + f);
if (mAdded.contains(f)) {
throw new IllegalStateException("Already added " + f);
}
synchronized (mAdded) {
// 添加进mAdded成员中
mAdded.add(f);
}
}
}
// Build the back stack.
// 后退栈数据恢复
if (fms.mBackStack != null) {
mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);
for (int i=0; i<fms.mBackStack.length; i++) {
BackStackRecord bse = fms.mBackStack[i].instantiate(this);
if (DEBUG) {
Log.v(TAG, "restoreAllState: back stack #" + i
+ " (index " + bse.mIndex + "): " + bse);
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
bse.dump(" ", pw, false);
pw.close();
}
mBackStack.add(bse);
if (bse.mIndex >= 0) {
setBackStackIndex(bse.mIndex, bse);
}
}
} else {
mBackStack = null;
}
if (fms.mPrimaryNavActiveWho != null) {
mPrimaryNav = mActive.get(fms.mPrimaryNavActiveWho);
dispatchParentPrimaryNavigationFragmentChanged(mPrimaryNav);
}
this.mNextFragmentIndex = fms.mNextFragmentIndex;
}
该方法中利用保存在FragmentManagerState中的数据进行状态恢复,其中在利用FragmentState恢复Fragment数据时,会将mSavedFragmentState赋值给Fragment的mSavedFragmentState成员。
mSavedFragmentState中保存了Fragment中的自定义存储数据和视图树状态
之后随着FragmentActivity调度Fragment显示,在Fragment的各生命周期阶段中,可以使用mSavedFragmentState保存的数据恢复。
进入FragmentManagerImpl的生命周期状态调度方法moveToState:
[FragmentManagerImpl.java]
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
// ···
if (f.mState <= newState) {
// ···
switch (f.mState) {
case Fragment.INITIALIZING:
if (newState > Fragment.INITIALIZING) {
if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
if (f.mSavedFragmentState != null) {
f.mSavedFragmentState.setClassLoader(mHost.getContext()
.getClassLoader());
// 获取保存的视图树状态
f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG);
Fragment target = getFragment(f.mSavedFragmentState,
FragmentManagerImpl.TARGET_STATE_TAG);
f.mTargetWho = target != null ? target.mWho : null;
if (f.mTargetWho != null) {
f.mTargetRequestCode = f.mSavedFragmentState.getInt(
FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
}
if (f.mSavedUserVisibleHint != null) {
f.mUserVisibleHint = f.mSavedUserVisibleHint;
f.mSavedUserVisibleHint = null;
} else {
// 获取保存的可见状态
f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
}
if (!f.mUserVisibleHint) {
f.mDeferStart = true;
if (newState > Fragment.ACTIVITY_CREATED) {
newState = Fragment.ACTIVITY_CREATED;
}
}
}
// ···
if (f.mParentFragment == null) {
mHost.onAttachFragment(f);
} else {
f.mParentFragment.onAttachFragment(f);
}
dispatchOnFragmentAttached(f, mHost.getContext(), false);
if (!f.mIsCreated) {
dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
// 触发Fragment的onCreate回调方法,并传入bundle
f.performCreate(f.mSavedFragmentState);
dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
} else {
// 派发Fragment的子Fragment的状态恢复
f.restoreChildFragmentState(f.mSavedFragmentState);
f.mState = Fragment.CREATED;
}
}
// fall through
case Fragment.CREATED:
// We want to unconditionally run this anytime we do a moveToState that
// moves the Fragment above INITIALIZING, including cases such as when
// we move from CREATED => CREATED as part of the case fall through above.
if (newState > Fragment.INITIALIZING) {
ensureInflatedFragmentView(f);
}
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
// ···
}
f.mContainer = container;
// 触发Fragment的onCreateView回调方法,并传入bundle
f.performCreateView(f.performGetLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView.setSaveFromParentEnabled(false);
if (container != null) {
container.addView(f.mView);
}
if (f.mHidden) {
f.mView.setVisibility(View.GONE);
}
// 触发Fragment的onViewCreated回调方法,并传入bundle
f.onViewCreated(f.mView, f.mSavedFragmentState);
dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,
false);
// Only animate the view if it is visible. This is done after
// dispatchOnFragmentViewCreated in case visibility is changed
f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE)
&& f.mContainer != null;
} else {
f.mInnerView = null;
}
}
// 触发Fragment的onActivityCreated回调方法,并传入bundle
f.performActivityCreated(f.mSavedFragmentState);
dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
// 调用mInnerView的restoreHierarchyState方法传入mSavedViewState进行视图树状态恢复。
// 然后回调onViewStateRestored方法并传入bundle。
f.restoreViewState(f.mSavedFragmentState);
}
// mSavedFragmentState赋值为空
f.mSavedFragmentState = null;
}
// fall through
case Fragment.ACTIVITY_CREATED:
if (newState > Fragment.ACTIVITY_CREATED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
f.performStart();
dispatchOnFragmentStarted(f, false);
}
// fall through
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
f.performResume();
dispatchOnFragmentResumed(f, false);
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
} else if (f.mState > newState) { /* ··· */ }
// ···
}
从该方法中可以看出,在Fragment的生命周期回调方法中收到的savedInstanceState入参即为Fragment的mSavedFragmentState,在派发完成后又会将mSavedFragmentState赋值为空。
这里看下提交事务的两个方法:commit、commitAllowingStateLoss,顾名思义,它们一个在提交时不允许状态丢失、另一个允许。
[BackStackRecord.java]
public int commit() {
return commitInternal(false);
}
public int commitAllowingStateLoss() {
return commitInternal(true);
}
都调用了同一个方法commitInternal,只是传入参数不同,一个传false,另一个传true。
继续看commitInternal方法:
[BackStackRecord.java]
int commitInternal(boolean allowStateLoss) {
// ···
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
allowStateLoss参数直接传入添加事务队列的方法。
[FragmentManagerImpl.java]
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
// 不允许状态丢失时,首先进行检查
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
// 当FragmentActivity已经destroyed或持有FragmentHostCallback为空时,若不允许状态丢失,将抛出异常。
if (allowStateLoss) {
// This FragmentManager isn't attached, so drop the entire transaction.
return;
}
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<>();
}
mPendingActions.add(action);
scheduleCommit();
}
}
是否允许状态丢失,就是在添加事务进队列前,检查状态,以及是否抛出异常。
进入checkStateLoss方法:
[FragmentManagerImpl.java]
private void checkStateLoss() {
// 检查状态,判断是否抛异常
if (isStateSaved()) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
}
@Override
public boolean isStateSaved() {
// See saveAllState() for the explanation of this. We do this for
// all platform versions, to keep our behavior more consistent between
// them.
// onSaveInstanceState时mStateSaved将置为true,onStop时mStopped将置为true
return mStateSaved || mStopped;
}
不允许在执行onSaveInstanceState回调方法后再添加Fragment事务操作。因为Fragment的状态保存是在onSaveInstanceState阶段中,此后若再变更FragmentManagerImpl中的Fragment,这些Fragment的状态不会进行保存。
onSaveInstanceState回调在Android P及以上版本触发时机在onStop之后,在低版本触发时机在onStop之前。
FragmentActivity在onSaveInstanceState回调方法中,调用FragmentManagerImpl通知其管理的Fragment进行状态保存。保存过程中会触发Fragment的onSaveInstanceState回调,可通过重写该方法保存自定义数据。若Fragment有设置view,还将进行视图树的保存。
FragmentActivity在onCreate回调方法中,判断savedInstanceState参数是否有值,之后通知FragmentManagerImpl进行状态恢复,实例化Fragment并将存储着状态的bundle赋值给mSavedFragmentState成员。
在Fragment从创建到显示的生命周期状态生长阶段,通过mSavedFragmentState成员来恢复数据和视图树,会将mSavedFragmentState作为入参调用对应生命周期回调方法,完成后再清除mSavedFragmentState。Fragment子类可在onCreate和onActivityCreated中恢复自定义数据。