Activity 启动之栈管理与 LaunchMode 判定

当 Activity 的启动请求进入 ATMS 后,最核心的逻辑就是:这个 Activity 应该放在哪个任务栈(Task)里? 这涉及到对 LaunchMode、Intent Flags 以及 TaskAffinity 的综合判定。

1. 核心角色:ActivityStarter

ActivityStarter 是启动流程中的“决策者”。它负责解析启动参数,并调用 startActivityUnchecked 开始处理栈逻辑。

2. LaunchMode 与 栈分配逻辑表

启动模式 ATMS 的核心逻辑 典型表现
standard 不做检查,直接创建新实例。 每次启动都会压入当前栈顶。
singleTop 检查目标栈顶。若已是该实例,回调 onNewIntent 防止栈顶重复创建。
singleTask 在全局寻找是否存在对应 taskAffinity 的栈。若有则移至前台并清理其上方所有 Activity (Clear Top)。 确保一个任务栈中只有一个实例。
singleInstance 强制创建一个新的任务栈,且该栈只能有这一个实例。 独占一个任务栈(如电话界面)。

3. Intent Flags 的影响

代码中通过 Intent.setFlags() 设置的参数优先级高于 XML 定义。

  • FLAG_ACTIVITY_NEW_TASK:对应 singleTask 的基本行为,寻找或创建新栈。
  • FLAG_ACTIVITY_CLEAR_TOP:如果栈中已存在该实例,销毁其上的所有 Activity。
  • FLAG_ACTIVITY_REORDER_TO_FRONT:将已存在的实例移到栈顶,不销毁中间的 Activity。

4. 栈管理的关键步骤

  1. findTask:根据 taskAffinityFlags 寻找匹配的 TaskRecord
  2. computeStack:确定目标 Activity 应该落在哪个 ActivityStack(在 Android 10+ 主要是 DisplayContent 下的容器)。
  3. resumeFocusedStacksTopActivities:将目标栈移到最前台,准备执行显示逻辑。

5. 调试技巧

使用以下命令可以实时观察栈的变化,这是理解栈管理逻辑的“神技”:

1
adb shell dumpsys activity activities

关注点: 寻找 TaskRecord 节点,查看其内部的 ActivityRecord 列表及其 intent 信息。

, ,