深度剖析 Android Activity 状态保存与恢复机制:从源码层面解锁底层逻辑
本人掘金号,欢迎点击关注:掘金号地址
本人公众号,欢迎点击关注:公众号地址
一、引言
在 Android 开发的广袤天地中,Activity 作为与用户交互的核心组件,其状态保存与恢复机制宛如精密齿轮,默默保障应用在复杂多变的使用场景下稳定运行。无论是因系统资源紧张导致 Activity 被销毁重建,还是用户主动切换设备方向触发的配置变更,状态保存与恢复机制都肩负着保留用户操作进度、维持应用连贯性体验的重任。深入理解这一机制的底层实现,不仅是提升应用质量的关键,更是开发者进阶路上不可或缺的一环。本文将深入 Android 源码,逐行拆解 Activity 状态保存与恢复模块的工作原理,揭开其神秘面纱。
二、Activity 状态保存与恢复的基本概念
2.1 状态保存与恢复的定义
在 Android 系统中,状态保存指的是当 Activity 即将面临被销毁的风险时,系统自动或开发者手动将 Activity 当前的重要状态信息(如界面上用户输入的数据、滚动位置等)存储起来的过程。而状态恢复则是在 Activity 重新创建时,系统利用之前保存的状态信息,将 Activity 还原到之前状态的操作。这一机制确保了用户在使用应用过程中,即使遇到意外情况(如内存不足导致 Activity 被系统回收),也不会丢失关键数据和操作进度,极大提升了应用的用户体验。
2.2 触发状态保存与恢复的常见场景
- 系统内存不足:当系统内存紧张时,为了释放资源,可能会销毁后台或当前不可见的 Activity。一旦内存压力缓解,这些 Activity 可能需要重新创建并恢复到之前的状态。
- 配置变更:例如用户旋转设备屏幕,此时 Activity 的配置(如屏幕方向、语言等)发生改变,系统会销毁当前 Activity 并重新创建一个新的 Activity 以适配新的配置。在这个过程中,状态保存与恢复机制会介入,确保用户在旋转屏幕前的操作状态得以保留。
- 用户切换应用:当用户从当前应用切换到其他应用,然后再切回时,如果当前 Activity 在后台期间被系统销毁,就需要恢复其状态。
三、状态保存流程的源码分析
3.1 状态保存的触发点
当系统决定需要保存 Activity 的状态时,这一过程通常由 ActivityManagerService(AMS)发起。AMS 作为 Android 系统中管理 Activity 生命周期的核心服务,时刻监控着系统中各个 Activity 的状态。当满足特定条件(如内存不足、配置变更等)时,AMS 会向对应的 Activity 所在的进程发送指令,触发状态保存流程。
3.2 ActivityThread 中的状态保存处理
在应用进程中,ActivityThread 类起着至关重要的作用,它负责管理应用的主线程和 Activity 的生命周期。当 AMS 发出状态保存指令后,ActivityThread 会接收到相关通知并进行处理。以下是 ActivityThread 中与状态保存相关的关键方法和源码分析:
3.2.1 handleStopActivity 方法
java
java
// ActivityThread.java
public void handleStopActivity(IBinder token, boolean show, int configChanges,
int seq, boolean isChild, boolean keepActive) {
// 获取ActivityClientRecord对象,该对象保存了Activity的相关信息
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
// 设置Activity已停止的标志
r.activity.mFinished = true;
r.stopped = true;
r.paused = true;
r.visible = false;
r.configChangeFlags |= configChanges;
r.hideForNow =!show;
r.forceNewConfig = false;
r.setState(ON_STOP);
if (DEBUG_LIFECYCLE) Slog.v(TAG, "Finishing stop of " + r + " with flags "
+ r.configChangeFlags);
// 调用performStopActivityInner方法进一步处理
performStopActivityInner(r, "handleStopActivity", keepActive);
}
}
在handleStopActivity
方法中,首先通过mActivities
这个 Map 获取与当前 Activity 对应的ActivityClientRecord
对象。ActivityClientRecord
类保存了 Activity 的诸多重要信息,包括 Activity 的实例、生命周期状态等。获取到ActivityClientRecord
后,设置一系列与 Activity 状态相关的标志位,如mFinished
表示 Activity 已完成,stopped
、paused
、visible
等标志位也相应更新,同时记录配置变更的标志configChangeFlags
。最后调用performStopActivityInner
方法进行更深入的状态保存处理。
3.2.2 performStopActivityInner 方法
java
java
// ActivityThread.java
private void performStopActivityInner(ActivityClientRecord r, String reason,
boolean keepActive) {
// 判断是否需要保存Activity的状态
boolean shouldSaveState = r.isPreHoneycomb()
||!r.activity.mFinished
|| r.activity.mCalled;
if (shouldSaveState) {
// 调用callCallActivityOnSaveInstanceState方法保存状态
callCallActivityOnSaveInstanceState(r);
}
if (r.activity.mVisibleFromClient) {
// 处理Activity的可见性相关逻辑
if (DEBUG_VISIBILITY) Slog.v(TAG, "Updating visibility to "
+ (r.activity.mVisibleFromClient? "visible" : "invisible")
+ " for " + r);
try {
ActivityManager.getService().activityStopped(r.token,
r.activity.mVisibleFromClient);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
// 标记Activity已停止
r.activity.mStopped = true;
if (r.activity.mParent == null &&!keepActive) {
r.activity.mFinished = true;
}
}
在performStopActivityInner
方法中,首先判断是否需要保存 Activity 的状态。判断条件包括 Activity 的版本是否为 Android 3.0(Honeycomb)之前、Activity 是否完成以及mCalled
标志位等。如果需要保存状态,则调用callCallActivityOnSaveInstanceState
方法。接着处理 Activity 的可见性相关逻辑,通过 AMS 通知系统 Activity 已停止。最后更新 Activity 的停止状态标志。
3.2.3 callCallActivityOnSaveInstanceState 方法
java
java
// ActivityThread.java
private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
// 创建一个Bundle对象用于保存状态
Bundle icicle = new Bundle();
if (r.isPersistable()) {
// 如果Activity是可持久化的,创建一个PersistableBundle对象
PersistableBundle persistentState = new PersistableBundle();
r.persistentState = persistentState;
// 调用Instrumentation的callActivityOnSaveInstanceState方法
mInstrumentation.callActivityOnSaveInstanceState(r.activity, icicle, persistentState);
} else {
// 调用Instrumentation的callActivityOnSaveInstanceState方法
mInstrumentation.callActivityOnSaveInstanceState(r.activity, icicle);
}
r.state = icicle;
r.persistentState = null;
}
callCallActivityOnSaveInstanceState
方法主要负责创建用于保存状态的Bundle
对象。如果 Activity 是可持久化的(Android 5.0 及以上版本引入的概念,用于处理设备配置变更等情况),还会创建PersistableBundle
对象。然后通过mInstrumentation
调用callActivityOnSaveInstanceState
方法,将 Activity 实例以及创建好的Bundle
对象传递进去,实际执行状态保存操作。最后将保存好状态的Bundle
对象赋值给ActivityClientRecord
的state
字段。
3.3 Instrumentation 在状态保存中的作用
Instrumentation 类在 Android 系统中扮演着重要的角色,它为应用程序和系统之间提供了一个桥梁。在 Activity 状态保存过程中,Instrumentation 负责调用 Activity 的具体状态保存方法。以下是 Instrumentation 中callActivityOnSaveInstanceState
方法的源码分析:
java
java
// Instrumentation.java
public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
// 调用Activity的performSaveInstanceState方法
activity.performSaveInstanceState(outState);
}
public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
PersistableBundle outPersistentState) {
// 调用Activity的performSaveInstanceState方法
activity.performSaveInstanceState(outState, outPersistentState);
}
这两个重载的callActivityOnSaveInstanceState
方法,最终都是调用 Activity 的performSaveInstanceState
方法,将用于保存状态的Bundle
对象传递给 Activity,让 Activity 进行具体的状态保存操作。
3.4 Activity 的状态保存实现
在 Activity 类中,performSaveInstanceState
方法是状态保存的核心实现。以下是该方法的源码分析:
java
java
// Activity.java
final void performSaveInstanceState(Bundle outState) {
// 调用onSaveInstanceState方法
onSaveInstanceState(outState);
// 保存Dialog的状态
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
// 保存转场动画相关状态
Parcelable transitionState = mWindow.getAttributes().windowAnimations;
if (transitionState != null) {
outState.putParcelable(WINDOW_TRANSITION_TAG, transitionState);
}
if (mActionBar != null) {
// 保存ActionBar的状态
mActionBar.performSaveInstanceState(outState);
}
if (mUiThread != null) {
// 保存用户界面线程相关状态
mUiThread.saveState(outState);
}
if (mFragments != null) {
// 保存Fragment的状态
mFragments.saveAllState();
}
if (mVoiceInteractor != null) {
// 保存语音交互相关状态
mVoiceInteractor.saveInstanceState(outState);
}
if (mAssistManager != null) {
// 保存辅助功能相关状态
mAssistManager.saveInstanceState(outState);
}
if (mActivityTransitionState!= null) {
// 保存Activity转场动画状态
mActivityTransitionState.saveState(outState);
}
}
final void performSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
// 调用onSaveInstanceState方法
onSaveInstanceState(outState, outPersistentState);
// 保存Dialog的状态
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
// 保存转场动画相关状态
Parcelable transitionState = mWindow.getAttributes().windowAnimations;
if (transitionState != null) {
outState.putParcelable(WINDOW_TRANSITION_TAG, transitionState);
}
if (mActionBar!= null) {
// 保存ActionBar的状态
mActionBar.performSaveInstanceState(outState);
}
if (mUiThread!= null) {
// 保存用户界面线程相关状态
mUiThread.saveState(outState);
}
if (mFragments!= null) {
// 保存Fragment的状态
mFragments.saveAllState();
}
if (mVoiceInteractor!= null) {
// 保存语音交互相关状态
mVoiceInteractor.saveInstanceState(outState);
}
if (mAssistManager!= null) {
// 保存辅助功能相关状态
mAssistManager.saveInstanceState(outState);
}
if (mActivityTransitionState!= null) {
// 保存Activity转场动画状态
mActivityTransitionState.saveState(outState);
}
if (outPersistentState!= null) {
// 保存可持久化的状态
mFragments.saveAllState(outPersistentState);
}
}
在performSaveInstanceState
方法中,首先调用onSaveInstanceState
方法,这是开发者可以重写的方法,用于保存自定义的状态信息。然后依次保存 Dialog 的状态、转场动画相关状态、ActionBar 的状态、用户界面线程相关状态、Fragment 的状态、语音交互相关状态、辅助功能相关状态以及 Activity 转场动画状态等。如果存在可持久化的Bundle
对象(outPersistentState
),还会保存可持久化的 Fragment 状态。
3.5 onSaveInstanceState 方法详解
java
java
// Activity.java
protected void onSaveInstanceState(Bundle outState) {
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
if (mActionBar!= null) {
mActionBar.performSaveInstanceState(outState);
}
if (mUiThread!= null) {
mUiThread.saveState(outState);
}
if (mFragments!= null) {
mFragments.saveAllState();
}
if (mVoiceInteractor!= null) {
mVoiceInteractor.saveInstanceState(outState);
}
if (mAssistManager!= null) {
mAssistManager.saveInstanceState(outState);
}
if (mActivityTransitionState!= null) {
mActivityTransitionState.saveState(outState);
}
}
protected void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
if (outPersistentState!= null) {
mFragments.saveAllState(outPersistentState);
}
onSaveInstanceState(outState);
}
onSaveInstanceState
方法有两个重载版本。默认实现中,它会保存一系列与 Activity 相关的状态信息。首先保存Window
层次结构的状态,通过调用mWindow.saveHierarchyState()
方法。如果 ActionBar 存在,保存 ActionBar 的状态。接着保存用户界面线程、Fragment、语音交互、辅助功能以及 Activity 转场动画等相关状态。在第二个重载版本中,如果存在可持久化的Bundle
对象(outPersistentState
),会先保存可持久化的 Fragment 状态,然后调用第一个重载版本的onSaveInstanceState
方法保存其他状态。
3.6 Window 层次结构的状态保存
在 Activity 的状态保存过程中,Window
层次结构的状态保存至关重要,它负责保存 Activity 界面上所有 View 的状态。以下是PhoneWindow
类中saveHierarchyState
方法的源码分析:
java
java
// PhoneWindow.java
public Bundle saveHierarchyState() {
// 创建一个Bundle对象用于保存状态
Bundle state = new Bundle();
if (mDecor == null) {
return state;
}
// 保存View树的状态
SparseArray<Parcelable> views = new SparseArray<>();
mDecor.saveHierarchyState(views);
if (views.size() > 0) {
state.putSparseParcelableArray(VIEWS_TAG, views);
}
// 保存焦点View的ID
View focused = findFocus();
if (focused!= null) {
state.putInt(FOCUS_TAG, focused.getId());
}
// 保存Panel的状态
savePanelState(state);
return state;
}
在saveHierarchyState
方法中,首先创建一个Bundle
对象state
用于保存状态。如果mDecor
(即 Activity 的顶级 View)为空,则直接返回空的Bundle
。接着创建一个SparseArray<Parcelable>
对象views
,用于保存 View 树的状态。通过调用mDecor.saveHierarchyState(views)
方法,将 View 树的状态保存到views
中。如果views
中保存了状态信息,则将其放入state
中。然后查找当前获得焦点的 View,并将其 ID 保存到state
中。最后调用savePanelState(state)
方法保存 Panel(如 PopupWindow 等)的状态,最终返回保存好状态的Bundle
对象。
3.7 View 的状态保存
View 类提供了saveHierarchyState
方法用于保存自身及其子 View 的状态。以下是该方法的源码分析:
java
java
// View.java
public void saveHierarchyState(SparseArray<Parcelable> container) {
// 保存自身的状态
Parcelable state = onSaveInstanceState();
if (mID!= NO_ID && state!= null) {
container.put(mID, state);
}
if (this instanceof ViewGroup) {
// 如果是ViewGroup,递归保存子View的状态
ViewGroup group = (ViewGroup) this;
final int count = group.getChildCount();
for (int i = 0; i < count; i++) {
group.getChildAt(i).saveHierarchyState(container);
}
}
}
protected Parcelable onSaveInstanceState() {
// 创建一个BaseSavedState对象,包含View的ID
Parcelable superState = super.onSaveInstanceState();
if (mID == NO_ID) {
return superState;
}
return new BaseSavedState(superState);
}
在saveHierarchyState
方法中,首先调用onSaveInstanceState
方法保存自身的状态。如果 View 有设置 ID 且保存的状态不为空,则将状态保存到container
中。如果当前 View 是ViewGroup
,则递归调用子 View 的saveHierarchyState
方法,保存所有子 View 的状态。
onSaveInstanceState
方法默认创建一个BaseSavedState
对象,该对象包含了 View 的 ID 信息。如果 View 没有设置 ID,则直接返回父类保存的状态。
3.8 Fragment 的状态保存
在 Activity 中,如果包含 Fragment,Fragment 的状态也需要保存。FragmentManager 负责管理 Fragment 的状态保存操作。以下是FragmentController
类中saveAllState
方法的源码分析:
java
java
// FragmentController.java
public void saveAllState(Bundle outState, PersistableBundle outPersistentState) {
if (mActive == null) {
return;
}
// 创建一个ArrayList用于保存Fragment的状态
ArrayList
java
java
// FragmentController.java
public void saveAllState(Bundle outState, PersistableBundle outPersistentState) {
if (mActive == null) {
return;
}
// 创建一个ArrayList用于保存Fragment的状态
ArrayList<FragmentState> active = new ArrayList<>();
int N = mActive.size();
Fragment[] fragments = new Fragment[N];
mActive.values().toArray(fragments);
for (int i = 0; i < N; i++) {
Fragment f = fragments[i];
if (f != null) {
if (f.mIndex < 0) {
// 如果Fragment的索引小于0,说明该Fragment还未被添加到FragmentManager中,跳过
continue;
}
FragmentState fs = new FragmentState(f);
active.add(fs);
if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
// 如果Fragment的状态大于INITIALIZING且还没有保存过状态
fs.mSavedFragmentState = saveFragmentBasicState(f);
if (f.mTargetIndex >= 0) {
// 如果Fragment有目标Fragment
if (fs.mSavedFragmentState == null) {
fs.mSavedFragmentState = new Bundle();
}
// 保存目标Fragment的索引
fs.mSavedFragmentState.putInt(
FragmentManagerImpl.ARG_TARGET_INDEX, f.mTargetIndex);
if (f.mTargetRequestCode != 0) {
// 保存目标Fragment的请求码
fs.mSavedFragmentState.putInt(
FragmentManagerImpl.ARG_TARGET_REQUEST_CODE, f.mTargetRequestCode);
}
}
}
if (outPersistentState != null && f.mRetainInstance) {
// 如果存在可持久化的Bundle对象且Fragment设置了保留实例
saveFragmentInstanceState(f, outPersistentState);
}
}
}
if (active.size() > 0) {
// 如果有需要保存状态的Fragment,将其保存到outState中
outState.putParcelableArrayList(
FragmentManagerImpl.KEY_ACTIVE_FRAGMENTS, active);
}
// 保存Fragment的事务状态
ArrayList<BackStackRecordState> backStack = null;
if (mBackStack != null) {
N = mBackStack.size();
if (N > 0) {
backStack = new ArrayList<>();
for (int i = 0; i < N; i++) {
BackStackRecord bs = mBackStack.get(i);
backStack.add(new BackStackRecordState(bs));
}
}
}
if (backStack != null) {
// 如果有需要保存的事务状态,将其保存到outState中
outState.putParcelableArrayList(
FragmentManagerImpl.KEY_BACK_STACK_ENTRIES, backStack);
}
// 保存当前的Fragment索引
outState.putInt(FragmentManagerImpl.KEY_LAST_SEQUENCE_NUMBER, mNextFragmentIndex);
outState.putInt(FragmentManagerImpl.KEY_LAST_BACK_STACK_ID, mMaxBackStackId);
}
在 saveAllState
方法中,首先检查 mActive
是否为空,如果为空则直接返回。接着创建一个 ArrayList<FragmentState>
类型的 active
列表,用于存储需要保存状态的 Fragment
。遍历 mActive
中的所有 Fragment
,对于每个 Fragment
,如果其索引小于 0,说明该 Fragment
还未被添加到 FragmentManager
中,跳过该 Fragment
。否则,创建一个 FragmentState
对象 fs
,并将其添加到 active
列表中。
如果 Fragment
的状态大于 INITIALIZING
且还没有保存过状态,则调用 saveFragmentBasicState
方法保存 Fragment
的基本状态。如果 Fragment
有目标 Fragment
,则将目标 Fragment
的索引和请求码保存到 fs.mSavedFragmentState
中。
如果存在可持久化的 Bundle
对象 outPersistentState
且 Fragment
设置了保留实例(mRetainInstance
为 true
),则调用 saveFragmentInstanceState
方法保存 Fragment
的可持久化状态。
如果 active
列表中有元素,则将其保存到 outState
中。接着处理 Fragment
的事务状态,将 mBackStack
中的每个 BackStackRecord
转换为 BackStackRecordState
对象,并保存到 backStack
列表中。如果 backStack
列表不为空,则将其保存到 outState
中。
最后,将当前的 Fragment
索引和最大的 BackStack
ID 保存到 outState
中。
3.8.1 saveFragmentBasicState 方法
java
java
// FragmentController.java
Bundle saveFragmentBasicState(Fragment f) {
// 创建一个Bundle对象用于保存状态
Bundle result = new Bundle();
// 保存Fragment的类名
result.putString(FragmentManagerImpl.ARG_CLASS_NAME, f.getClass().getName());
if (f.mArguments != null) {
// 保存Fragment的参数
result.putBundle(FragmentManagerImpl.ARG_ARGS, f.mArguments);
}
if (f.mSavedViewState != null) {
// 保存Fragment的视图状态
result.putSparseParcelableArray(FragmentManagerImpl.ARG_VIEW_STATE, f.mSavedViewState);
}
if (f.mUserVisibleHint) {
// 保存Fragment的用户可见性提示
result.putBoolean(FragmentManagerImpl.ARG_USER_VISIBLE_HINT, true);
}
if (f.mTargetIndex >= 0) {
// 保存目标Fragment的索引
result.putInt(FragmentManagerImpl.ARG_TARGET_INDEX, f.mTargetIndex);
if (f.mTargetRequestCode != 0) {
// 保存目标Fragment的请求码
result.putInt(FragmentManagerImpl.ARG_TARGET_REQUEST_CODE, f.mTargetRequestCode);
}
}
if (f.mBackStackNesting > 0) {
// 保存Fragment的BackStack嵌套层数
result.putInt(FragmentManagerImpl.ARG_BACK_STACK_NESTING, f.mBackStackNesting);
}
// 调用Fragment的onSaveInstanceState方法保存自定义状态
f.performSaveInstanceState(result);
return result;
}
saveFragmentBasicState
方法用于保存 Fragment
的基本状态。首先创建一个 Bundle
对象 result
,然后依次保存 Fragment
的类名、参数、视图状态、用户可见性提示、目标 Fragment
的索引和请求码、BackStack
嵌套层数等信息。最后调用 Fragment
的 performSaveInstanceState
方法,让 Fragment
保存自己的自定义状态。
3.8.2 saveFragmentInstanceState 方法
java
java
// FragmentController.java
private void saveFragmentInstanceState(Fragment f, PersistableBundle outPersistentState) {
// 创建一个PersistableBundle对象用于保存可持久化状态
PersistableBundle state = new PersistableBundle();
// 调用Fragment的onSaveInstanceState方法保存可持久化状态
f.performSaveInstanceState(state);
if (!state.isEmpty()) {
// 如果保存的状态不为空,将其保存到outPersistentState中
outPersistentState.putPersistableBundle(
FragmentManagerImpl.KEY_RETAINED_FRAGMENT_STATE_PREFIX + f.mWho, state);
}
}
saveFragmentInstanceState
方法用于保存 Fragment
的可持久化状态。首先创建一个 PersistableBundle
对象 state
,然后调用 Fragment
的 performSaveInstanceState
方法,让 Fragment
保存自己的可持久化状态。如果保存的状态不为空,则将其保存到 outPersistentState
中,使用 Fragment
的 mWho
作为键的前缀。
3.9 总结状态保存流程
整个 Activity 状态保存流程从 AMS 发起通知开始,经过 ActivityThread、Instrumentation 的处理,最终由 Activity 及其包含的各个组件(如 View、Fragment 等)完成状态保存。具体步骤如下:
- AMS 通知:当系统需要保存 Activity 状态时,AMS 向对应的 Activity 所在进程发送通知。
- ActivityThread 处理 :ActivityThread 接收到通知后,调用
handleStopActivity
方法,在该方法中进一步调用performStopActivityInner
方法判断是否需要保存状态,如果需要则调用callCallActivityOnSaveInstanceState
方法。 - Instrumentation 调用 :
callCallActivityOnSaveInstanceState
方法通过mInstrumentation
调用callActivityOnSaveInstanceState
方法,进而调用 Activity 的performSaveInstanceState
方法。 - Activity 保存状态 :在
performSaveInstanceState
方法中,调用onSaveInstanceState
方法保存自定义状态,同时保存 Dialog、ActionBar、View、Fragment 等组件的状态。 - View 状态保存 :View 通过
saveHierarchyState
方法保存自身及其子 View 的状态。 - Fragment 状态保存 :FragmentManager 通过
saveAllState
方法保存 Fragment 的状态,包括基本状态和可持久化状态。
四、状态恢复流程的源码分析
4.1 状态恢复的触发点
当 Activity 由于某些原因(如配置变更、内存不足被销毁后重新创建)需要恢复状态时,系统会在 Activity 的创建过程中触发状态恢复流程。通常在 Activity 的 onCreate
或 onRestoreInstanceState
方法中进行状态恢复操作。
4.2 ActivityThread 中的状态恢复处理
在 Activity 重新创建时,ActivityThread 会负责接收并处理保存的状态信息,将其传递给 Activity 进行恢复。以下是 ActivityThread 中与状态恢复相关的关键方法和源码分析:
4.2.1 handleLaunchActivity 方法
java
java
// ActivityThread.java
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
// 调用performLaunchActivity方法创建并启动Activity
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
if (!r.activity.mFinished && pendingActions != null) {
// 处理挂起的事务操作
pendingActions.setOldState(r.state);
pendingActions.setRestoreInstanceState(true);
pendingActions.setCallOnPostCreate(true);
}
handleResumeActivity(r.token, false, r.isForward,
"LAUNCH_ACTIVITY", pendingActions, false);
}
return a;
}
在 handleLaunchActivity
方法中,首先调用 performLaunchActivity
方法创建并启动 Activity。如果 Activity 创建成功,记录当前的配置信息,并处理挂起的事务操作。最后调用 handleResumeActivity
方法将 Activity 置于恢复状态。
4.2.2 performLaunchActivity 方法
java
java
// ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 获取Activity的信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
// 获取Activity的类名
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
// 创建Activity的实例
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
// 如果存在保存的状态信息,调用Activity的onCreate方法并传入状态信息
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances,
r.config, r.referrer, r.voiceInteractor, window,
r.configCallback, r.assistToken);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.state != null) {
// 如果存在保存的状态信息,调用Activity的onCreate方法并传入状态信息
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
// 调用Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, null, r.persistentState);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.state != null) {
// 如果存在保存的状态信息,调用Activity的onRestoreInstanceState方法
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
mInstrumentation.callActivityOnPostCreate(activity, r.state, r.persistentState);
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r);
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
在 performLaunchActivity
方法中,首先获取 Activity 的信息,包括类名、包信息等。然后使用 mInstrumentation.newActivity
方法创建 Activity 的实例。如果存在保存的状态信息(r.state
不为空),则将其类加载器设置为当前 Activity 的类加载器。
接着创建 Activity 的上下文,并调用 activity.attach
方法将 Activity 与上下文、ActivityThread 等关联起来。根据是否存在保存的状态信息,调用 mInstrumentation.callActivityOnCreate
方法传入相应的状态信息。
如果 Activity 创建成功且未被销毁,调用 activity.performStart
方法启动 Activity。如果存在保存的状态信息,调用 mInstrumentation.callActivityOnRestoreInstanceState
方法进行状态恢复。最后调用 mInstrumentation.callActivityOnPostCreate
方法完成 Activity 的创建后操作。
4.3 Instrumentation 在状态恢复中的作用
Instrumentation 在状态恢复过程中同样起着桥梁的作用,负责调用 Activity 的具体状态恢复方法。以下是 Instrumentation 中与状态恢复相关的方法的源码分析:
4.3.1 callActivityOnCreate 方法
java
java
// Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
// 调用Activity的performCreate方法
activity.performCreate(icicle);
}
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
// 调用Activity的performCreate方法
activity.performCreate(icicle, persistentState);
}
这两个重载的 callActivityOnCreate
方法,最终都是调用 Activity 的 performCreate
方法,将保存的状态信息(Bundle
或 PersistableBundle
)传递给 Activity,让 Activity 进行创建操作。
4.3.2 callActivityOnRestoreInstanceState 方法
java
java
// Instrumentation.java
public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
// 调用Activity的performRestoreInstanceState方法
activity.performRestoreInstanceState(savedInstanceState);
}
public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState,
PersistableBundle persistentState) {
// 调用Activity的performRestoreInstanceState方法
activity.performRestoreInstanceState(savedInstanceState, persistentState);
}
这两个重载的 callActivityOnRestoreInstanceState
方法,最终都是调用 Activity 的 performRestoreInstanceState
方法,将保存的状态信息传递给 Activity,让 Activity 进行状态恢复操作。
4.4 Activity 的状态恢复实现
在 Activity 类中,performCreate
和 performRestoreInstanceState
方法是状态恢复的核心实现。以下是这两个方法的源码分析:
4.4.1 performCreate 方法
java
java
// Activity.java
final void performCreate(Bundle icicle) {
// 调用onCreate方法
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
// 调用onCreate方法
onCreate(icicle, persistentState);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
performCreate
方法有两个重载版本,分别处理不同类型的状态信息。在这两个方法中,首先调用 onCreate
方法,这是开发者可以重写的方法,用于在 Activity 创建时进行初始化操作,并传入保存的状态信息。然后调用 mActivityTransitionState.readState
方法读取 Activity 转场动画的状态。最后调用 performCreateCommon
方法完成一些通用的创建操作。
4.4.2 performRestoreInstanceState 方法
java
java
// Activity.java
final void performRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// 调用onRestoreInstanceState方法
onRestoreInstanceState(savedInstanceState);
// 恢复Window层次结构的状态
mWindow.restoreHierarchyState(savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG));
// 恢复ActionBar的状态
if (mActionBar != null) {
mActionBar.performRestoreInstanceState(savedInstanceState);
}
// 恢复Fragment的状态
if (mFragments != null) {
mFragments.restoreAllState(savedInstanceState,
getNonConfigInstance());
}
}
}
final void performRestoreInstanceState(Bundle savedInstanceState,
PersistableBundle persistentState) {
if (savedInstanceState != null) {
// 调用onRestoreInstanceState方法
onRestoreInstanceState(savedInstanceState, persistentState);
// 恢复Window层次结构的状态
mWindow.restoreHierarchyState(savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG));
// 恢复ActionBar的状态
if (mActionBar != null) {
mActionBar.performRestoreInstanceState(savedInstanceState);
}
// 恢复Fragment的状态
if (mFragments != null) {
mFragments.restoreAllState(savedInstanceState,
getNonConfigInstance());
if (persistentState != null) {
mFragments.restoreAllState(persistentState);
}
}
}
}
performRestoreInstanceState
方法有两个重载版本,分别处理不同类型的状态信息。在这两个方法中,首先检查保存的状态信息是否为空。如果不为空,调用 onRestoreInstanceState
方法,这是开发者可以重写的方法,用于在 Activity 恢复状态时进行自定义的恢复操作。然后依次恢复 Window 层次结构的状态、ActionBar 的状态和 Fragment 的状态。如果存在可持久化的状态信息(persistentState
不为空),则调用 mFragments.restoreAllState
方法恢复可持久化的 Fragment 状态。
4.5 Window 层次结构的状态恢复
在 Activity 的状态恢复过程中,Window
层次结构的状态恢复同样重要,它负责恢复 Activity 界面上所有 View 的状态。以下是 PhoneWindow
类中 restoreHierarchyState
方法的源码分析:
java
java
// PhoneWindow.java
public void restoreHierarchyState(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// 恢复View树的状态
SparseArray<Parcelable> views = savedInstanceState.getSparseParcelableArray(VIEWS_TAG);
if (views != null) {
mDecor.restoreHierarchyState(views);
}
// 恢复焦点View的状态
int focusedViewId = savedInstanceState.getInt(FOCUS_TAG, View.NO_ID);
if (focusedViewId != View.NO_ID) {
View focusedView = mDecor.findViewById(focusedViewId);
if (focusedView != null) {
focusedView.requestFocus();
}
}
// 恢复Panel的状态
restorePanelState(savedInstanceState);
}
}
在 restoreHierarchyState
方法中,首先检查保存的状态信息是否为空。如果不为空,从 savedInstanceState
中获取保存的 View 树状态信息(SparseArray<Parcelable>
类型),并调用 mDecor.restoreHierarchyState
方法恢复 View 树的状态。然后获取保存的焦点 View 的 ID,查找对应的 View 并请求焦点。最后调用 restorePanelState
方法恢复 Panel 的状态。
4.6 View 的状态恢复
View 类提供了 restoreHierarchyState
方法用于恢复自身及其子 View 的状态。以下是该方法的源码分析:
java
java
// View.java
public void restoreHierarchyState(SparseArray<Parcelable> container) {
// 恢复自身的状态
if (mID != NO_ID) {
Parcelable state = container.get(mID);
if (state != null) {
onRestoreInstanceState(state);
}
}
if (this instanceof ViewGroup) {
// 如果是ViewGroup,递归恢复子View的状态
ViewGroup group = (ViewGroup) this;
final int count = group.getChildCount();
for (int i = 0; i < count; i++) {
group.getChildAt(i).restoreHierarchyState(container);
}
}
}
protected void onRestoreInstanceState(Parcelable state) {
// 恢复父类的状态
super.onRestoreInstanceState(state);
}
在 restoreHierarchyState
方法中,首先检查 View 是否有设置 ID。如果有设置 ID,从 container
中获取对应的状态信息,并调用 onRestoreInstanceState
方法恢复自身的状态。如果当前 View 是 ViewGroup
,则递归调用子 View 的 restoreHierarchyState
方法,恢复所有子 View 的状态。
onRestoreInstanceState
方法默认调用父类的 onRestoreInstanceState
方法,恢复父类的状态。
4.7 Fragment 的状态恢复
在 Activity 中,如果包含 Fragment,Fragment 的状态也需要恢复。FragmentManager 负责管理 Fragment 的状态恢复操作。以下是 FragmentController
类中 restoreAllState
方法的源码分析:
java
java
// FragmentController.java
public void restoreAllState(Bundle savedInstanceState, FragmentManagerNonConfig nonConfig) {
if (savedInstanceState == null) {
return;
}
// 恢复Fragment的活跃状态
ArrayList<FragmentState> activeFragments = savedInstanceState.getParcelableArrayList(
FragmentManagerImpl.KEY_ACTIVE_FRAGMENTS);
if (activeFragments != null) {
mActive = new ArrayMap<>();
int N = activeFragments.size();
for (int i = 0; i < N; i++) {
FragmentState fs = activeFragments.get(i);
if (fs != null) {
Fragment f = fs.instantiate(mHost, mParent, nonConfig);
if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
mActive.put(f.mIndex, f);
}
}
}
// 恢复Fragment的BackStack状态
ArrayList<BackStackRecordState> backStack = savedInstanceState.getParcelableArrayList(
FragmentManagerImpl.KEY_BACK_STACK_ENTRIES);
if (backStack != null) {
mBackStack = new ArrayList<>();
int N = backStack.size();
for (int i = 0; i < N; i++) {
BackStackRecordState bss = backStack.get(i);
if (bss != null) {
BackStackRecord bs = new BackStackRecord(mHost, bss);
if (DEBUG) Log.v(TAG, "restoreAllState: back stack #" + i + ": " + bs);
mBackStack.add(bs);
}
}
}
// 恢复当前的Fragment索引
mNextFragmentIndex = savedInstanceState.getInt(FragmentManagerImpl.KEY_LAST_SEQUENCE_NUMBER);
mMaxBackStackId = savedInstanceState.getInt(FragmentManagerImpl.KEY_LAST_BACK_STACK_ID);
}
public void restoreAllState(PersistableBundle savedInstanceState) {
if (savedInstanceState == null) {
return;
}
// 恢复可持久化的Fragment状态
for (String key : savedInstanceState.keySet()) {
if (key.startsWith(FragmentManagerImpl.KEY_RETAINED_FRAGMENT_STATE_PREFIX)) {
String who = key.substring(FragmentManagerImpl.KEY_RETAINED_FRAGMENT_STATE_PREFIX.length());
Fragment f = findFragmentByWho(who);
if (f != null) {
PersistableBundle state = savedInstanceState.getPersistableBundle(key);
f.performRestoreInstanceState(state);
}
}
}
}
restoreAllState
方法有两个重载版本,分别处理不同类型的状态信息。在第一个重载版本中,首先检查保存的状态信息是否为空。如果不为空,从 savedInstanceState
中获取保存的活跃 Fragment 状态信息(ArrayList<FragmentState>
类型),并将其恢复到 mActive
中。然后获取保存的 BackStack 状态信息(ArrayList<BackStackRecordState>
类型),并将其恢复到 mBackStack
中。最后恢复当前的 Fragment 索引和最大的 BackStack ID。
在第二个重载版本中,检查保存的可持久化状态信息是否为空。如果不为空,遍历 savedInstanceState
中的所有键,找到以 FragmentManagerImpl.KEY_RETAINED_FRAGMENT_STATE_PREFIX
开头的键,获取对应的可持久化状态信息,并调用 Fragment
的 performRestoreInstanceState
方法恢复 Fragment
的可持久化状态。
4.8 总结状态恢复流程
整个 Activity 状态恢复流程从 ActivityThread 创建 Activity 开始,经过 Instrumentation 的调用,最终由 Activity 及其包含的各个组件(如 View、Fragment 等)完成状态恢复。具体步骤如下:
- ActivityThread 创建 Activity :在
performLaunchActivity
方法中,创建 Activity 的实例,并根据是否存在保存的状态信息,调用mInstrumentation.callActivityOnCreate
方法传入相应的状态信息。 - Instrumentation 调用 Activity 方法 :
callActivityOnCreate
方法调用 Activity 的performCreate
方法,callActivityOnRestoreInstanceState
方法调用 Activity 的performRestoreInstanceState
方法。 - Activity 恢复状态 :在
performRestoreInstanceState
方法中,调用onRestoreInstanceState
方法进行自定义状态恢复,同时恢复 Window 层次结构、ActionBar、Fragment 等组件的状态。 - View 状态恢复 :View 通过
restoreHierarchyState
方法恢复自身及其子 View 的状态。 - Fragment 状态恢复 :FragmentManager 通过
restoreAllState
方法恢复 Fragment 的状态,包括活跃状态、BackStack 状态和可持久化状态。
五、特殊情况与注意事项
5.1 配置变更时的状态保存与恢复
在 Android 开发中,配置变更(如屏幕旋转、语言切换等)是常见的情况。当发生配置变更时,默认情况下,Activity 会被销毁并重新创建,这就需要进行状态保存与恢复操作。
5.1.1 系统默认处理
当配置变更发生时,系统会自动调用 Activity 的 onSaveInstanceState
方法保存状态,然后销毁 Activity。在重新创建 Activity 时,会将保存的状态信息传递给 onCreate
或 onRestoreInstanceState
方法进行恢复。
5.1.2 手动处理配置变更
开发者可以通过在 AndroidManifest.xml
中为 Activity 设置 android:configChanges
属性来手动处理配置变更。例如:
xml
java
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize">
...
</activity>
当设置了 android:configChanges
属性后,发生指定的配置变更时,Activity 不会被销毁重建,而是会调用 onConfigurationChanged
方法。开发者可以在该方法中进行自定义的配置变更处理,而不需要依赖状态保存与恢复机制。
5.2 内存不足时的状态保存与恢复
当系统内存不足时,为了释放资源,可能会销毁一些处于后台或不可见状态的 Activity。在这种情况下,Activity 的状态保存与恢复机制同样会发挥作用。
5.2.1 系统自动销毁 Activity
当系统检测到内存不足时,会根据一定的策略(如 LRU 算法)选择一些 Activity 进行销毁。在销毁 Activity 之前,系统会调用 onSaveInstanceState
方法保存状态。
5.2.2 Activity 重新创建与状态恢复
当用户再次回到该 Activity 时,系统会重新创建 Activity,并将之前保存的状态信息传递给 onCreate
或 onRestoreInstanceState
方法进行恢复。
5.3 手动销毁 Activity 时的状态处理
当用户手动按下返回键或调用 finish
方法销毁 Activity 时,系统不会调用 onSaveInstanceState
方法保存状态。因为在这种情况下,用户明确表示要结束当前 Activity,不需要保存状态。
5.4 自定义状态保存与恢复
在实际开发中,开发者可能需要保存和恢复一些自定义的状态信息。可以通过重写 Activity 的 onSaveInstanceState
和 onRestoreInstanceState
方法来实现。
5.4.1 重写 onSaveInstanceState 方法
java
java
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// 保存自定义状态信息
outState.putString("custom_key", "custom_value");
}
5.4.2 重写 onRestoreInstanceState 方法
java
java
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// 恢复自定义状态信息
String customValue = savedInstanceState.getString("custom_key");
if (customValue != null) {
// 使用恢复的状态信息
}
}
5.5 状态保存与恢复的性能考虑
状态保存与恢复机制虽然方便,但在某些情况下可能会影响应用的性能。例如,当保存和恢复的状态信息较多时,会增加 Activity 的创建和销毁时间,导致界面响应变慢。
5.5.1 优化策略
- 减少不必要的状态保存:只保存必要的状态信息,避免保存大量无用的数据。
- 使用 ViewModel:ViewModel 可以在配置变更时保留数据,减少状态保存与恢复的工作量。
- 异步处理:对于一些耗时的状态保存与恢复操作,可以考虑使用异步线程进行处理,避免阻塞主线程。
六、总结与展望
6.1 总结
通过对 Android Activity 状态保存与恢复机制的源码分析,我们深入了解了这一机制的实现原理和工作流程。状态保存与恢复机制在 Android 系统中起着至关重要的作用,它确保了 Activity 在各种情况下(如配置变更、内存不足等)能够正确保存和恢复状态,为用户提供了流畅、连贯的使用体验。
整个状态保存流程从 AMS 发起通知开始,经过 ActivityThread、Instrumentation 的处理,最终由 Activity 及其包含的各个组件(如 View、Fragment 等)完成状态保存。状态恢复流程则从 ActivityThread 创建 Activity 开始,同样经过 Instrumentation 的调用,由 Activity 及其组件完成状态恢复。
在实际开发中,开发者可以根据具体需求重写 onSaveInstanceState
和 onRestoreInstanceState
方法,实现自定义的状态保存与恢复。同时,需要注意一些特殊情况(如配置变更、内存不足等)的处理,以及状态保存与恢复的性能优化。
6.2 展望
随着 Android 系统的不断发展,Activity 状态保存与恢复机制也可能会得到进一步的优化和改进。未来可能会出现更加高效、灵活的状态保存与恢复方式,例如支持更多类型的数据保存、更好地处理大数据量的状态信息等。
同时,随着 Android Jetpack 组件的不断完善,如 ViewModel、SavedStateHandle 等,开发者可以更加方便地进行状态管理,减少对传统状态保存与恢复机制的依赖。这将使得开发者能够更加专注于业务逻辑的实现,提高开发效率和应用的质量。
总之,深入理解 Activity 状态保存与恢复机制对于 Android 开发者来说是非常重要的,它不仅能够帮助我们解决实际开发中的问题,还能为我们未来的开发工作打下坚实的基础。