本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
Activity 数据保存与恢复机制是 Android 系统确保用户界面状态连续性的重要机制。其核心在于 onSaveInstanceState() 和 onRestoreInstanceState() 方法的调用时机,以及 ActivityThread 中 mActivities 字段在状态管理中的作用。
数据保存机制
当 Activity 即将被销毁时(如屏幕旋转、内存不足等),系统会调用 onSaveInstanceState() 方法来保存当前 Activity 的状态。这个方法接收一个 Bundle 对象作为参数,开发中可以将需要保存的数据存入该 Bundle 对象中。
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("key", "value");
}
数据的保存是通过 ActivityClientRecord 的 state 字段来实现的,该字段类型为 Bundle。在 performPauseActivity 方法中,系统会调用 callActivityOnSaveInstanceState 方法,将状态保存到 ActivityClientRecord 的 state 字段中。
数据恢复机制
当 Activity 被重建时,系统会将之前保存的 Bundle 对象传递给 onRestoreInstanceState() 方法或 onCreate() 方法中的 savedInstanceState 参数。恢复过程发生在 Activity 的生命周期中,onRestoreInstanceState() 方法在 onStart() 之后、onResume() 之前被调用。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
String value = savedInstanceState.getString("key");
}
}
mActivities 字段的作用
在 ActivityThread 类中,mActivities 是一个 HashMap,用于存储当前进程中所有已创建的 ActivityClientRecord 对象。这个字段在状态保存和恢复过程中发挥关键作用:
mActivities 与 ActivityClientRecord 的关系
mActivities 是 ActivityThread 类中的一个 ArrayMap<IBinder, ActivityClientRecord> 类型的字段,用于存储当前进程中所有已启动的 Activity 的客户端记录。每个 ActivityClientRecord 对象都包含了一个 token 字段,该字段是 IBinder 类型,用于唯一标识一个 Activity 实例。
// ActivityThread.java 中的定义
private final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
状态保存过程
当 Activity 即将被停止时,系统会调用 performStopActivity 方法来保存 Activity 的状态。在这个过程中,系统会通过 mActivities 查找对应的 ActivityClientRecord 对象,并调用 callActivityOnSaveInstanceState 方法来保存状态。
// ActivityThread.java 中的 performStopActivity 方法
final void performStopActivity(IBinder token, boolean saveState, String reason) {
ActivityClientRecord r = mActivities.get(token);
performStopActivityInner(r, null /* stopInfo */, saveState, false /* finalStateRequest */, reason);
}
// 在 performStopActivityInner 中
private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean saveState, boolean finalStateRequest, String reason) {
// …
if (shouldSaveState && isPreP) {
callActivityOnSaveInstanceState(r);
}
// …
}
在 callActivityOnSaveInstanceState 方法中,系统会调用 Instrumentation 的 callActivityOnSaveInstanceState 方法,该方法会将状态保存到 ActivityClientRecord 的 state 字段中。
// ActivityThread.java 中的 callActivityOnSaveInstanceState 方法
private void callActivityOnSaveInstanceState(ActivityClientRecord r) {
// …
mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
// …
}
对应关系的建立机制
Token 作为唯一标识符:每个 Activity 都有一个全局唯一的 IBinder 类型的 token,这个 token 既是 Activity 的标识符,也是两个记录对象关联的关键。
跨进程传递:当 Activity 启动时,AMS 会通过 ApplicationThread 的 scheduleLaunchActivity 方法将包含 token 的信息传递给应用进程。
映射关系建立:应用进程接收到启动信息后,会创建对应的 ActivityClientRecord 对象,并以 token 作为 key,ActivityClientRecord 对象作为 value 存储到 mActivities 中。
// ActivityThread.java 中的启动流程
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
// 通过 token 建立关联
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, …);
}
// ActivityThread.handleLaunchActivity 中
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 创建 ActivityClientRecord 并存入 mActivities
mActivities.put(r.token, r);
}
状态恢复过程
当 Activity 被重建时,系统会通过 mActivities 查找对应的 ActivityClientRecord 对象,并从 state 字段中获取之前保存的状态数据。
// ActivityThread.java 中的 handleResumeActivity 方法
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
// …
if (r.activity.mStateSaved) {
r.activity.onRestoreInstanceState(r.state);
}
// …
}
调用时机
onSaveInstanceState() 方法的调用时机取决于 targetSdkVersion:
- 对于 targetSdkVersion < 30 的应用,该方法在 onPause() 之后、onStop() 之前调用。
- 对于 targetSdkVersion >= 30 的应用,该方法在 onStop() 之后调用。
onRestoreInstanceState() 方法仅在 Activity 确实被系统销毁并重建时调用,通常在 onStart() 和 onResume() 之间调用。
状态保存触发条件
onSaveInstanceState() 方法会在以下情况下被调用:
总结
ActivityClientRecord
- 存在于每个应用进程中的 ActivityThread 类中
- 代表应用进程中一个 Activity 的客户端视图
- 包含 Activity 的运行时状态信息,如窗口对象、暂停状态等
- 与具体的 Activity 实例一一对应
Activity 的状态保存与恢复机制通过 onSaveInstanceState() 和 onRestoreInstanceState() 方法实现,而 ActivityThread 中的 mActivities 字段作为关键的数据结构,管理着 Activity 的生命周期状态。系统通过 mActivities 来获取 Activity 的状态信息,并在需要时进行保存和恢复,确保用户在 Activity 被销毁并重建后能够恢复到之前的状态。




