当 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. 栈管理的关键步骤
- findTask:根据
taskAffinity和Flags寻找匹配的TaskRecord。 - computeStack:确定目标 Activity 应该落在哪个
ActivityStack(在 Android 10+ 主要是DisplayContent下的容器)。 - resumeFocusedStacksTopActivities:将目标栈移到最前台,准备执行显示逻辑。
5. 调试技巧
使用以下命令可以实时观察栈的变化,这是理解栈管理逻辑的“神技”:
1 | adb shell dumpsys activity activities |
关注点: 寻找 TaskRecord 节点,查看其内部的 ActivityRecord 列表及其 intent 信息。