Android中ActivityRecord解析

307 阅读6分钟

一、ActivityRecord:Activity 的 “数字档案”

在 Android 系统中,ActivityRecord是 ActivityManagerService(AMS)用于管理 Activity 实例的核心数据结构,可视为 Activity 在系统层面的 “数字档案”。它不直接参与界面渲染,而是专注于记录 Activity 的关键信息,协调其与任务栈、进程及系统服务的交互。

1. 核心属性:档案里的关键信息

属性名作用描述
app指向所属进程记录(ProcessRecord),记录 Activity 运行的进程信息(如进程名、UID)。
task指向所属任务栈(TaskRecord),标识 Activity 属于哪个任务(如浏览器的多个标签页)。
info存储 Manifest 中声明的元数据(如android:launchMode、权限、主题)。
state生命周期状态(如RESUMED/PAUSED/STOPPED),由 AMS 根据用户操作或系统事件更新。
appToken跨进程通信令牌(继承自IApplicationToken.Stub),用于与窗口管理服务(WMS)交互窗口状态。
realActivity组件名(如com.example.App.MainActivity),标识具体的 Activity 类。

状态机示例

  • 当用户打开新 Activity 时,旧 Activity 状态从RESUMED变为PAUSED,新 Activity 状态变为RESUMED
  • 当 Activity 被用户按返回键关闭时,状态依次经过FINISHINGDESTROYINGDESTROYED

2. 与 TaskRecord 的关系:任务栈中的 “任务卡片”

TaskRecord代表一个 “任务栈”(如手机的 “最近任务” 列表中的一个条目),用于管理一组相关 Activity(如浏览器的主页、搜索页、详情页)。

  • 层级关系:一个TaskRecord包含多个ActivityRecord,按启动顺序组成后进先出(LIFO)的栈结构。

  • 核心作用

    • 维护 Activity 的启动顺序,支持返回键回退逻辑。
    • 根据启动模式(如singleTask)决定是否复用已有 Activity 或创建新实例。
    • 通过affinity属性定义任务栈的 “亲和性”(如指定某个任务栈属于特定用户或应用)。

二、ActivityStack 与 ActivityStackSupervisor:栈结构的管理者

1. ActivityStack:Activity 的物理容器

作用

  • 管理一个或多个TaskRecord,负责 Activity 的栈内调度(如栈顶 Activity 的恢复、暂停、移除)。

  • 维护栈内 Activity 的状态一致性,例如确保同一时刻只有一个 Activity 处于RESUMED状态。

核心属性

  • mResumedActivity:当前栈顶可见的 Activity(状态为RESUMED)。

  • mLastPausedActivity:最近一次暂停的 Activity(状态为PAUSED)。

  • mTaskHistory:存储该栈包含的所有TaskRecord,按任务创建顺序排列。

关键操作

  • resumeTopActivityLocked:恢复栈顶 Activity,触发其onResume回调,并暂停其他 Activity。

  • startPausingLocked:暂停当前 Activity,触发onPause回调,为新 Activity 启动做准备。

  • removeActivityLocked:从栈中移除 Activity,触发onDestroy回调(如用户按返回键关闭 Activity)。

示例场景
当用户从 Activity A 启动 Activity B 时:

  1. ActivityStack 调用startPausingLocked暂停 A(状态变为PAUSING)。
  2. 创建 Activity B 的ActivityRecord并加入栈顶。
  3. 调用resumeTopActivityLocked恢复 B(状态变为RESUMED),A 最终变为PAUSED状态。

2. ActivityStackSupervisor:全局栈调度中心

作用

  • 管理系统中所有ActivityStack(如主屏幕栈、应用栈、多窗口栈),协调不同栈之间的切换(如从主屏幕切换到最近任务)。

  • 处理多显示设备(如折叠屏、外接显示器)场景,为每个显示设备维护独立的ActivityDisplay和栈结构。

核心属性

  • mFocusedStack:当前获得焦点的栈(用户正在交互的栈)。
  • mHomeStack:主屏幕栈,存储桌面 Activity(如 Launcher)。
  • mActivityDisplays:按显示设备 ID(displayId)映射的ActivityDisplay,支持多屏独立显示不同栈。

三、Activity 栈关系:从单体到层级的管理架构

1. 栈结构的层级关系

Android 通过多层数据结构实现对 Activity 的高效管理,形成 “Supervisor → Display → Stack → Task → Activity” 的层级链:

  • ActivityStackSupervisor
    作为全局管理者,负责协调所有显示设备(如手机主屏、外接显示器)的 Activity 栈。

    • 核心作用:维护mActivityDisplays(按显示设备 ID 映射),每个显示设备对应一个ActivityDisplay

    • 默认栈

      • mHomeStack:主屏幕栈,存储桌面 Activity(如 Launcher),栈 ID 固定为 0。
      • mFocusedStack:当前用户交互的栈(如正在使用的应用栈)。
  • ActivityDisplay
    代表一个物理或虚拟显示设备(如折叠屏的不同分屏),包含一组ActivityStack

    • 单设备场景:默认只有一个ActivityDisplay,包含Home Stack(桌面)和App Stack(应用栈)。
    • 多设备场景:每个显示器独立管理自己的栈,如主屏显示社交应用,副屏显示视频应用。
  • ActivityStack
    具体的物理栈,存储同一显示设备中的任务栈(TaskRecord)。

    • 核心属性

      • mResumedActivity:栈顶可见的 Activity(状态为RESUMED)。
      • mTaskHistory:按创建顺序排列的任务栈列表,支持任务切换(如最近任务列表)。
  • TaskRecord
    逻辑任务单元,包含一组相关 Activity(如同一应用的多个页面)。

    • 核心逻辑

      • 按启动模式(如singleTask)决定是否复用栈内 Activity。
      • 通过affinity属性定义任务归属(如指定任务属于某个用户或应用)。
  • ActivityRecord
    单个 Activity 的系统记录,关联到所属的TaskRecordActivityStack

    • 反向引用链
      ActivityRecord.task → TaskRecord.stack → ActivityStack.mStackSupervisor → ActivityStackSupervisor
      便于系统从 Activity 快速回溯到全局管理节点。

2. 典型场景:单设备下的栈结构

  • 默认配置

    plaintext

    ActivityStackSupervisor  
      ├─ ActivityDisplay (displayId=0)  
      │   ├─ HomeStack (stackId=0, 桌面Activity)  
      │   └─ AppStack (stackId=1, 应用Activity)  
      │       └─ TaskRecord (taskId=1, 包含Activity A、B、C)  
      │
    

四、Activity 启动与停止流程:状态机与系统调度

1. 启动流程:从点击到界面显示的全链路

当用户触发startActivity(如点击按钮)时,系统通过以下步骤完成 Activity 的启动和界面显示:

步骤 1:客户端发起请求
  • 调用链
    Activity.startActivity() → ContextImpl.startActivity() → AMP.startActivity()(通过 Binder 调用 AMS)。

  • 关键操作

    • 封装启动参数(如 Intent、调用者信息),通过 Binder 传递给系统服务 AMS。
步骤 2:AMS 调度任务栈
  • 核心方法
    AMS.startActivityLocked() → ActivityStackSupervisor.resumeTopActivityInnerLocked()

  • 逻辑解析

    1. 查找或创建任务栈:根据 Activity 的启动模式(如singleTask)和亲和性(taskAffinity)确定所属任务栈(TaskRecord)。
    2. 暂停旧 Activity:若栈顶存在其他 Activity(如 Activity A),调用startPausingLocked()将其状态设为PAUSING,触发onPause回调。
    3. 创建新 ActivityRecord:生成ActivityRecord对象,记录启动参数、所属进程和任务栈。
步骤 3:启动目标进程(若需要)
  • 场景:若目标 Activity 所属进程未运行(如首次启动应用),AMS 通过startProcessLocked()请求 Zygote 创建新进程。

  • 进程通信

    • 新进程启动后,通过ActivityThread.attach()与 AMS 建立 Binder 连接(ATP.bindApplication)。
    • AMS 通过realStartActivityLocked()通知新进程加载 Activity,调用scheduleLaunchActivity()发送启动消息。
步骤 4:App 进程执行生命周期回调
  • Handler 消息驱动
    新进程的主线程 Handler(H)收到H.LAUNCH_ACTIVITY消息,触发以下操作:

    1. 创建 Activity 实例:通过反射调用Instrumentation.newActivity()创建 Activity 对象。
    2. 关联上下文:调用activity.attach()绑定ContextImplappToken,初始化窗口管理器(WMS)。
    3. 生命周期回调:依次调用onCreate()onStart()onResume(),界面渲染完成后状态变为RESUMED
步骤 5:更新栈状态与用户可见性
  • AMS 最终处理

    • 调用activityIdleInternalLocked()标记