欢迎光临
我们一直在努力

android中 Activity 的数据保存机制

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

   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 对象。这个字段在状态保存和恢复过程中发挥关键作用:

  • ‌状态保存‌:当系统调用 performPauseActivity 时,会通过 mActivities 获取对应的 ActivityClientRecord 对象,然后调用 callActivityOnSaveInstanceState 方法保存状态。
  • ‌状态恢复‌:当 Activity 重建时,系统通过 mActivities 获取对应的 ActivityClientRecord,从中获取保存的 Bundle 对象,然后调用 onRestoreInstanceState 方法恢复状态。
  • 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() 方法会在以下情况下被调用:

  • 用户按下 HOME 键
  • 从最近应用中选择运行其他程序
  • 按下电源键关闭屏幕
  • 从当前 Activity 启动新 Activity
  • 屏幕方向切换时(Activity 被销毁并重建)
  • 总结

    ActivityClientRecord

    • 存在于每个应用进程中的 ActivityThread 类中
    • 代表应用进程中一个 Activity 的客户端视图
    • 包含 Activity 的运行时状态信息,如窗口对象、暂停状态等
    • 与具体的 Activity 实例一一对应

    Activity 的状态保存与恢复机制通过 onSaveInstanceState() 和 onRestoreInstanceState() 方法实现,而 ActivityThread 中的 mActivities 字段作为关键的数据结构,管理着 Activity 的生命周期状态。系统通过 mActivities 来获取 Activity 的状态信息,并在需要时进行保存和恢复,确保用户在 Activity 被销毁并重建后能够恢复到之前的状态。

    赞(0)
    未经允许不得转载:171主机测评 » android中 Activity 的数据保存机制
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址