通常我们采用下面的方式保存Activity的状态
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
接下来我们从源码分析一下
protected void onSaveInstanceState(Bundle outState) {
//通知mWindow去保存层级状态
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
//保存Fragment的状态
Parcelable p = mFragments.saveAllState();
if (p != null) {
//把数据放到Bundle里
outState.putParcelable(FRAGMENTS_TAG, p);
}
if (mAutoFillResetNeeded) {
outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
getAutofillManager().onSaveInstanceState(outState);
}
getApplication().dispatchActivitySaveInstanceState(this, outState);
}
我们知道mWindow是PhoneWindow的实例,下面去看看
public Bundle saveHierarchyState() {
Bundle outState = new Bundle();
//mContentParent是DecorView中一个id为content的容器,我们Activitiy中的布局
就是添加到这个mContent中
if (mContentParent == null) {
return outState;
}
//创建一个容器,用来保存View层级结构
SparseArray<Parcelable> states = new SparseArray<Parcelable>();
//保存View树状态
mContentParent.saveHierarchyState(states);
//将状态存到Bundle中
outState.putSparseParcelableArray(VIEWS_TAG, states);
// 保存有焦点的View
View focusedView = mContentParent.findFocus();
if (focusedView != null) {
if (focusedView.getId() != View.NO_ID) {
outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
} else {
if (false) {
Log.d(TAG, "couldn't save which view has focus because the focused view "
+ focusedView + " has no id.");
}
}
}
return outState;
}
接下来我们看saveHierarchyState方法,由于ViewGroup没这个方法,所以我们去View里看
public void saveHierarchyState(SparseArray<Parcelable> container) {
dispatchSaveInstanceState(container);
}
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
//判断View是否有id以及是否允许保存
if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
//获取保存的结果
Parcelable state = onSaveInstanceState();
if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
throw new IllegalStateException(
"Derived class did not call super.onSaveInstanceState()");
}
if (state != null) {
// Log.i("View", "Freezing #" + Integer.toHexString(mID)
// + ": " + state);
//把结过放到容器中,键为View的id,值为状态
container.put(mID, state);
}
}
}
从上面的代码可以看出,一个View如果想要保存状态,则必须提供一个id,并且它是允许状态保存的,我们可以通过setSaveEnabled方法来决定是否能够保存
接下来我们看看ViewGroup的dispatchSaveInstanceState方法
@Override
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
super.dispatchSaveInstanceState(container);
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
View c = children[i];
if ((c.mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED) {
//保存每个子View的状态
c.dispatchSaveInstanceState(container);
}
}
}
到此,整个View的保存状态就完了,接下来我i们看看Fragment的保存
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
最终调用到了FragmentManagerImpl的saveAllState方法,,
下面是精简后的代码
if (mActive == null || mActive.size() <= 0) {
return null;
}
//获得当前活动中的Fragment
int N = mActive.size();
//创建对应的Fragment状态数据
FragmentState[] active = new FragmentState[N];
boolean haveFragments = false;
for (int i=0; i<N; i++) {
//获取活动中的每个Fragment
Fragment f = mActive.valueAt(i);
if (f != null) {
if (f.mIndex < 0) {
throwException(new IllegalStateException(
"Failure saving state: active " + f
+ " has cleared index: " + f.mIndex));
}
haveFragments = true;
//创建每个Fragment对应的状态对象FragmentState
FragmentState fs = new FragmentState(f);
active[i] = fs;
if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
//代码1
fs.mSavedFragmentState = saveFragmentBasicState(f);
if (f.mTarget != null) {
if (f.mTarget.mIndex < 0) {
throwException(new IllegalStateException(
"Failure saving state: " + f
+ " has target not in fragment manager: " + f.mTarget));
}
if (fs.mSavedFragmentState == null) {
fs.mSavedFragmentState = new Bundle();
}
putFragment(fs.mSavedFragmentState,
FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
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);
}
}
在代码1处,把saveFragmentBasicState方法的返回值给了FragmentState对象的
mSavedFragmentState属性,这个属性是一个Bundle对象,下面我们看看saveFragmentBasicState方法
Bundle saveFragmentBasicState(Fragment f) {
Bundle result = null;
if (mStateBundle == null) {
mStateBundle = new Bundle();
}
//代码2,调用Fragment对象的performSaveInstanceState方法
f.performSaveInstanceState(mStateBundle);
dispatchOnFragmentSaveInstanceState(f, mStateBundle, false);
if (!mStateBundle.isEmpty()) {
result = mStateBundle;
mStateBundle = null;
}
if (f.mView != null) {
//保存Fragment视图数结构
saveFragmentViewState(f);
}
if (f.mSavedViewState != null) {
if (result == null) {
result = new Bundle();
}
//将上面保存的视图树的结果放到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
result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
}
return result;
}
代码2处条用了Fragment的一个方法,如下
void performSaveInstanceState(Bundle outState) {
//执行Fragment的onSaveInstanceState方法,这是一个空方法
onSaveInstanceState(outState);
if (mChildFragmentManager != null) {
Parcelable p = mChildFragmentManager.saveAllState();
if (p != null) {
outState.putParcelable(FragmentActivity.FRAGMENTS_TAG, p);
}
}
}
下面我们看保存Fragment视图数结构的代码
void saveFragmentViewState(Fragment f) {
if (f.mView == null) {
return;
}
if (mStateArray == null) {
mStateArray = new SparseArray<Parcelable>();
} else {
mStateArray.clear();
}
//和上面View的保存状态一样
f.mView.saveHierarchyState(mStateArray);
if (mStateArray.size() > 0) {
f.mSavedViewState = mStateArray;
mStateArray = null;
}
}
总结
通过上面的分析,我们发现在saveFragmentBasicState中主要做了两件事,
1.保存Fragment的数据
2.保存Fragment视图树结构
然后把这些数据给了FragmentState的一个Bundle属性,所以FragmentState这个对象对Fragment的状态保存很重要。
状态恢复源码分析
我们看Activity的onRestoreInstanceState方法
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (mWindow != null) {
//获取保存的视图树信息
Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
if (windowState != null) {
//调用PhoneWindow的restoreHierarchyState方法
mWindow.restoreHierarchyState(windowState);
}
}
}
PhoneWindow的方法
@Override
public void restoreHierarchyState(Bundle savedInstanceState) {
if (mContentParent == null) {
return;
}
//获取保存的状态信息
SparseArray<Parcelable> savedStates
= savedInstanceState.getSparseParcelableArray(VIEWS_TAG);
if (savedStates != null) {
mContentParent.restoreHierarchyState(savedStates);
}
// restore the focused view
int focusedViewId = savedInstanceState.getInt(FOCUSED_ID_TAG, View.NO_ID);
if (focusedViewId != View.NO_ID) {
View needsFocus = mContentParent.findViewById(focusedViewId);
if (needsFocus != null) {
needsFocus.requestFocus();
} else {
Log.w(TAG,
"Previously focused view reported id " + focusedViewId
+ " during save, but can't be found during restore.");
}
}
调用了View的方法
public void restoreHierarchyState(SparseArray<Parcelable> container) {
dispatchRestoreInstanceState(container);
}
protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
//判断当前View是否有id
if (mID != NO_ID) {
//根据id获取对应的数据
Parcelable state = container.get(mID);
if (state != null) {
// Log.i("View", "Restoreing #" + Integer.toHexString(mID)
// + ": " + state);
mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
//恢复数据
onRestoreInstanceState(state);
if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
throw new IllegalStateException(
"Derived class did not call super.onRestoreInstanceState()");
}
}
}
}
恢复Fragment状态,我们看看Activity的onCreate方法
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
//获取Fragment的数据
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.fragments : null);
}
mFragments.dispatchCreate();
getApplication().dispatchActivityCreated(this, savedInstanceState);
下面我们看看restoreAllState方法,这个方法定义在FragmentManager中
void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
if (state == null) return;
FragmentManagerState fms = (FragmentManagerState)state;
if (fms.mActive == null) return;
for (int i=0; i<fms.mActive.length; i++) {
//获取Fragment的状态数据
FragmentState fs = fms.mActive[i];
Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig);
if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
mActive.put(f.mIndex, 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;
}
我们去看FragmentState的instantiate方法
public Fragment instantiate(FragmentHostCallback host, FragmentContainer container,
Fragment parent, FragmentManagerNonConfig childNonConfig) {
if (mInstance == null) {
final Context context = host.getContext();
if (mArguments != null) {
mArguments.setClassLoader(context.getClassLoader());
}
if (container != null) {
mInstance = container.instantiate(context, mClassName, mArguments);
} else {
//初始化Fragment
mInstance = Fragment.instantiate(context, mClassName, mArguments);
}
//把之前保存的状态信息赋值给新建的对象
if (mSavedFragmentState != null) {
mSavedFragmentState.setClassLoader(context.getClassLoader());
mInstance.mSavedFragmentState = mSavedFragmentState;
}
mInstance.setIndex(mIndex, parent);
mInstance.mFromLayout = mFromLayout;
mInstance.mRestored = true;
mInstance.mFragmentId = mFragmentId;
mInstance.mContainerId = mContainerId;
mInstance.mTag = mTag;
mInstance.mRetainInstance = mRetainInstance;
mInstance.mDetached = mDetached;
mInstance.mHidden = mHidden;
mInstance.mFragmentManager = host.mFragmentManager;
if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
"Instantiated fragment " + mInstance);
}
mInstance.mChildNonConfig = childNonConfig;
return mInstance;
}
这里只是恢复了Fragment的一部分的数据,View视图树还没创建,所以别的数据是在Fragment进入生命周期才恢复的,我们再回到Activity的onCreate中,调用了
mFragments.dispatchCreate();方法,此时调用的是FragmentManager的方法
public void dispatchCreate() {
mStateSaved = false;
dispatchMoveToState(Fragment.CREATED);
}
private void dispatchMoveToState(int state) {
if (mAllowOldReentrantBehavior) {
moveToState(state, false);
} else {
try {
mExecutingActions = true;
moveToState(state, false);
} finally {
mExecutingActions = false;
}
}
execPendingActions();
}
然后看moveToState方法
void moveToState(int newState, boolean always) {
if (mAdded != null) {
final int numAdded = mAdded.size();
for (int i = 0; i < numAdded; i++) {
Fragment f = mAdded.get(i);
//看此方法
moveFragmentToExpectedState(f);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
}
void moveFragmentToExpectedState(final Fragment f) {
if (f == null) {
return;
}
int nextState = mCurState;
if (f.mRemoving) {
if (f.isInBackStack()) {
nextState = Math.min(nextState, Fragment.CREATED);
} else {
nextState = Math.min(nextState, Fragment.INITIALIZING);
}
}
//看此方法
moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
}
在moveToState方法里调用了下面的方法
//调用Fragment的onActivityCreated方法
f.performActivityCreated(f.mSavedFragmentState);
dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
//恢复Fragment视图状态
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}
从上面的代码我们可以看出,恢复Fragment视图数据的时机是在onActivityCreated方法之后,
final void restoreViewState(Bundle savedInstanceState) {
if (mSavedViewState != null) {
//恢复View树状态
mView.restoreHierarchyState(mSavedViewState);
mSavedViewState = null;
}
mCalled = false;
onViewStateRestored(savedInstanceState);
if (!mCalled) {
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onViewStateRestored()");
}
}
@CallSuper
public void onViewStateRestored(Bundle savedInstanceState) {
mCalled = true;
}
总结
在Fragment中我们可以通过onSaveInstanceState方法保存数据,需要注意的是,Fragment并没有onRestoreInStanceState方法,我们一般重写onViewStateRestored方法恢复数据