Android中级——Activity数据恢复过程
Activity数据恢复
- onSaveInstanceState()
- onRestoreInstanceState()
- 扩展
onSaveInstanceState()
在Activity调用onStop()之前调用会onSaveInstanceState(),如下
final void performStopActivity(IBinder token, boolean saveState, String reason) {ActivityClientRecord r = mActivities.get(token);performStopActivityInner(r, null /* stopInfo */, saveState, false /* finalStateRequest */,reason);
}private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean saveState, boolean finalStateRequest, String reason) {......callActivityOnStop(r, saveState, reason);......
}private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {......final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null && !r.isPreHoneycomb();final boolean isPreP = r.isPreP();if (shouldSaveState && isPreP) {callActivityOnSaveInstanceState(r);}try {r.activity.performStop(r.mPreserveWindow, reason);}......
}
onSaveInstanceState()存储Window视图树、调用Fragment、ActivityLifecycleCallbacks的onSaveInstanceState()
protected void onSaveInstanceState(@NonNull Bundle outState) {outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);Parcelable p = mFragments.saveAllState();if (p != null) {outState.putParcelable(FRAGMENTS_TAG, p);}if (mAutoFillResetNeeded) {outState.putBoolean(AUTOFILL_RESET_NEEDED, true);getAutofillManager().onSaveInstanceState(outState);}dispatchActivitySaveInstanceState(outState);
}
上面调用到PhoneWindow的saveHierarchyState()
@Override
public Bundle saveHierarchyState() {Bundle outState = new Bundle();if (mContentParent == null) {return outState;}SparseArray<Parcelable> states = new SparseArray<Parcelable>();mContentParent.saveHierarchyState(states); outState.putSparseParcelableArray(VIEWS_TAG, states); //存储视图树的结构final View focusedView = mContentParent.findFocus();if (focusedView != null && focusedView.getId() != View.NO_ID) {outState.putInt(FOCUSED_ID_TAG, focusedView.getId()); //存储当前焦点所在View的ID,持有焦点的View必须设置ID,否则无法恢复}SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();savePanelState(panelStates);if (panelStates.size() > 0) {outState.putSparseParcelableArray(PANELS_TAG, panelStates); //存储面板信息}if (mDecorContentParent != null) {SparseArray<Parcelable> actionBarStates = new SparseArray<Parcelable>();mDecorContentParent.saveToolbarHierarchyState(actionBarStates);outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates); //存储actionBar}return outState;
}
mContentParent即是Activity中setContentView()所设置的根布局,调用到View的saveHierarchyState()方法
public void saveHierarchyState(SparseArray<Parcelable> container) {dispatchSaveInstanceState(container);
}
若当前是ViewGroup,则遍历child调用其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) {c.dispatchSaveInstanceState(container);}}
}
若当前是View,则从onSaveInstanceState()获取state根据当前View的ID保存到SparseArray
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;Parcelable state = onSaveInstanceState();......if (state != null) {......container.put(mID, state);}}
}
onSaveInstanceState()需要由子类自身去实现,以TextView为例,保存了字符串、间距、位置信息等
@Override
public Parcelable onSaveInstanceState() {Parcelable superState = super.onSaveInstanceState();final boolean freezesText = getFreezesText();boolean hasSelection = false;int start = -1;int end = -1;if (mText != null) {start = getSelectionStart();end = getSelectionEnd();if (start >= 0 || end >= 0) {hasSelection = true;}}if (freezesText || hasSelection) {SavedState ss = new SavedState(superState);if (freezesText) {if (mText instanceof Spanned) {final Spannable sp = new SpannableStringBuilder(mText);if (mEditor != null) {removeMisspelledSpans(sp);sp.removeSpan(mEditor.mSuggestionRangeSpan);}ss.text = sp;} else {ss.text = mText.toString();}}if (hasSelection) {ss.selStart = start;ss.selEnd = end;}if (isFocused() && start >= 0 && end >= 0) {ss.frozenWithFocus = true;}ss.error = getError();if (mEditor != null) {ss.editorState = mEditor.saveInstanceState();}return ss;}return superState;
}
onRestoreInstanceState()
在performLaunchActivity()中,取出ActivityClientRecord中的state传给Activity的OnCreate()方法,在正常启动时,state为空,需要对state进行判空
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {try {......if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}......r.activity = activity;} ......synchronized (mResourcesManager) {mActivities.put(r.token, r);}}......return activity;
}
在handleStartActivity()中先调用onStart(),再调用OnRestoreInstanceState()
@Override
public void handleStartActivity(IBinder token, PendingTransactionActions pendingActions) {final ActivityClientRecord r = mActivities.get(token);final Activity activity = r.activity;......activity.performStart("handleStartActivity");......if (pendingActions.shouldRestoreInstanceState()) {if (r.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);}}......
}
扩展
Activity并非每次退出都会调用onSaveInstanceState(),如当用户按Back键主动退出时,下面列举几种调用onSaveInstanceState()的情况
- 按下Home键
- 长按Home键选中运行其他程序
- 按下电源键息屏
- 从Activity启动一个新的Activity
- 屏幕方向切换
- 电话打入