Android Activity 启动模式和任务栈
在掌握 Activity 基本生命周期后,我们能完成单个 Activity 内的业务逻辑,但这不足以支撑优质的 APP 体验。Android 系统通过任务栈(Task Stack) 管理整个 APP 的 Activity 实例,合理调度任务栈是提升用户体验的关键。任务栈遵循先进后出(FILO) 的线性表结构:新启动的 Activity 会被压入栈顶并处于活动状态,其他 Activity 虽退出活动状态(触发 onStop()),但只要未触发 onDestroy(),就会保留在栈中。
默认情况下,点击返回键或调用 finish() 方法会移除栈顶 Activity,让栈内下一个 Activity 恢复活动状态。但通过 AndroidManifest.xml 中 android:launchMode 属性,或 Intent 携带的 Flag,可打破这一默认行为。
一、AndroidManifest 声明的启动模式
1. standard(标准模式)
standard 是所有 Activity 的默认启动模式,未显式指定时均采用此模式。该模式下,每次启动 Activity 都会创建全新的实例,新实例会被压入当前任务栈的栈顶,覆盖原有栈顶 Activity。
任务栈状态示意图
# 初始状态:栈内有 Activity A(栈底)
| |
| A | <-- 栈底
|________|
# 启动 Activity B(standard 模式)
| |
| B | <-- 栈顶(新实例)
| A |
|________|
# 再次启动 Activity B(standard 模式)
| |
| B₂ | <-- 栈顶(全新 B 实例)
| B₁ |
| A |
|________|
2. singleTop(栈顶复用模式)
指定为 singleTop 模式的 Activity,启动时系统会先检查当前栈顶是否是该 Activity 实例:
- 若栈顶已是目标 Activity,不会创建新实例,而是复用栈顶实例并调用其
onNewIntent()方法; - 若栈顶不是目标 Activity,则创建新实例并压入栈顶。
该模式适用于接收消息后展示的界面(如通知栏点击打开的详情页),避免重复创建相同的栈顶页面。
任务栈状态示意图
# 初始状态:栈内有 A、B、C(C 为 singleTop 模式,栈顶)
| |
| C | <-- 栈顶(singleTop)
| B |
| A |
|________|
# 再次启动 Activity C
| |
| C | <-- 复用原实例,调用 onNewIntent()
| B |
| A |
|________|
# 启动 Activity D 后,再启动 Activity C
| |
| C₂ | <-- 栈顶(新实例,因原 C 不在栈顶)
| D |
| C₁ |
| B |
| A |
|________|
3. singleTask(栈内复用模式)
singleTask 是比 singleTop 范围更广的复用模式:启动时系统会检查整个任务栈是否存在目标 Activity 实例:
- 若存在:将该实例移动到栈顶,并销毁其上方所有 Activity;
- 若不存在:创建新实例并压入栈顶。
注意:
- 同一 APP 内启动
singleTaskActivity 时,仅在当前任务栈内检查/复用;- 其他程序启动该 Activity 时,会为其创建新任务栈;
- 若
singleTaskActivity 已存在于后台任务栈,启动后该后台任务栈会整体切换到前台。
任务栈状态示意图
# 初始状态:当前任务栈有 A、B、C、D(C 为 singleTask 模式)
| |
| D | <-- 栈顶
| C |
| B |
| A |
|________|
# 启动 Activity C(singleTask 模式)
| |
| C | <-- 栈顶(移动上来)
| B |
| A |
|________|
# D 被销毁(onDestroy() 触发)
# 跨 APP 启动 singleTask 的 Activity C(无现有实例)
# 新任务栈创建:
任务栈1(原APP):| A | B |
任务栈2(新): | C | <-- 独立栈,仅含 C
4. singleInstance(单实例模式)
singleInstance 是最特殊的启动模式:
- 声明为此模式的 Activity 会被放入全新的独立任务栈,且该任务栈中仅存在这一个 Activity;
- 该 Activity 实例全局共享,再次启动时不会创建新实例,直接调出该任务栈并将 Activity 置于前台。
任务栈状态示意图
# 启动 singleInstance 的 Activity X
任务栈1(原APP):| A | B |
任务栈2(独立):| X | <-- 仅含 X,全局唯一
# 从原 APP 再次启动 Activity X
任务栈1(原APP):| A | B |
任务栈2(独立):| X | <-- 复用实例,切换到前台
重要注意事项
若在 singleTop 或 singleInstance 模式的 Activity A 中,通过 startActivityForResult() 启动 Activity B,系统会直接返回 Activity.RESULT_CANCELED,不会等待 B 的返回结果。
原因是 Framework 层限制:不同 Task 间默认不支持数据回传,若需传递数据,需通过 Intent 显式传递。
二、其他补充说明
- 除了在
AndroidManifest.xml中声明启动模式,也可通过 Intent 设置 Flag(如FLAG_ACTIVITY_SINGLE_TOP、FLAG_ACTIVITY_NEW_TASK等),指定单次启动的模式; AndroidManifest.xml还提供了清理任务栈的标签(如android:clearTaskOnLaunch、android:finishOnTaskLaunch等),可参考官方 API 文档了解用法;- 任务栈的调度需结合项目实际需求,禁止滥用——错误的启动模式会导致页面跳转逻辑混乱、内存泄漏或用户操作不符合预期。
总结
- 任务栈核心规则是“先进后出”,
launchMode可打破默认的实例创建/栈管理逻辑; standard每次新建实例,singleTop复用栈顶,singleTask复用栈内实例并清理上方页面,singleInstance独占任务栈且全局唯一;singleTop/singleInstance不支持startActivityForResult()回传结果,需通过 Intent 传递数据。

浙公网安备 33010602011771号