一句话总结:
LaunchMode 是 Activity 的“开店模式”,决定了一个 Activity 在应用中能开多少家分店(实例),以及分店之间的跳转规则。不同模式会影响 Activity 的生命周期调用顺序和其在**任务栈(Task)**中的行为。
四种启动模式(LaunchMode)的核心区别
| 模式 | 核心规则 | 任务栈(Task)关系 | 复用时的生命周期 |
|---|---|---|---|
standard | 每次启动都创建新实例(默认)。 | 在启动它的任务栈中入栈。 | 不涉及复用,总是 onCreate -> onStart -> onResume。 |
singleTop | 如果实例已在栈顶,则复用;否则创建新实例。 | 与standard相同。 | onPause -> onNewIntent -> onResume。 |
singleTask | 检查整个任务栈中是否存在实例。若存在,则清空其上所有Activity并复用;若不存在,则创建。 | 默认在主任务栈。可通过taskAffinity指定归属的任务栈。 | onNewIntent -> onRestart -> onStart -> onResume。 |
singleInstance | 实例独占一个任务栈,该栈中有且只有这一个实例。 | 总是创建一个全新的任务栈来存放自己。 | 与singleTask相同。 |
场景与生命周期深度解析
1. standard (标准模式)
最简单的模式,每次调用startActivity()都会创建一个新的Activity实例,并压入当前的“任务栈”中。适用于绝大多数普通页面。
- 栈状态变化:
A-> (启动B) ->A -> B-> (再启动B) ->A -> B -> B - 生命周期: 每次启动都完整执行
onCreate(),onStart(),onResume()。
2. singleTop (栈顶复用模式)
当要启动的Activity正好位于当前任务栈的栈顶时,系统不会创建新的实例,而是直接复用,并回调其onNewIntent()方法。
-
应用场景: 接收通知跳转的页面、搜索结果页。可以防止用户连续点击通知或按钮,创建一堆重复的页面。
-
生命周期细节 (ActivityB为
singleTop且已在栈顶) :- 当再次尝试启动B时,B会经历
onPause()->onNewIntent()->onResume()。 - 关键点: 在
onNewIntent(intent)里,必须调用setIntent(intent),否则后续getIntent()获取的仍是旧的Intent数据。
- 当再次尝试启动B时,B会经历
3. singleTask (栈内单例模式)
启动时,系统会先寻找是否存在一个与该Activity的taskAffinity(任务亲和性)属性匹配的任务栈。
-
如果存在这样的栈:
- 检查栈内是否有该Activity的实例。如果有,则将它上面的所有其他Activity全部出栈(执行
onDestroy),使该实例回到栈顶,并调用其onNewIntent()。 - 如果没有实例,则在该栈顶部创建新实例。
- 检查栈内是否有该Activity的实例。如果有,则将它上面的所有其他Activity全部出栈(执行
-
如果不存在这样的栈:
- 创建一个新的任务栈(其
taskAffinity与该Activity匹配),然后将该Activity作为根Activity压入新栈。
- 创建一个新的任务栈(其
-
应用场景: 应用的主界面(如微信主页)、浏览器主页。确保应用的核心入口只有一个,并且返回时能清掉中间页面,直接回到主页。
-
生命周期细节 (栈: A -> B -> C, 此时启动A) :
- C和B会依次执行
onPause->onStop->onDestroy,被销毁出栈。 - A会回调
onNewIntent来接收新的启动意图,然后是onRestart->onStart->onResume。
- C和B会依次执行
4. singleInstance (全局单例模式)
这是最特殊的模式。一个singleInstance的Activity会独占一个新的任务栈。任何从这个Activity启动的其他Activity,都会被放入其他任务栈中(通常是启动它的那个任务栈),保证了该Activity所在的栈里永远只有它一个实例。
- 应用场景: 系统级的、需要与应用完全隔离的页面,如来电显示界面、闹钟提醒界面。
- 用户体验差异: 由于它独立于应用的返回栈,用户点击返回键时,可能会在两个应用(或两个任务栈)的界面之间来回切换,体验较为跳跃。
超越LaunchMode:Intent Flags的动态控制
LaunchMode是静态配置,而Intent Flags则提供了动态控制Activity启动行为的能力,其优先级更高。
-
Intent.FLAG_ACTIVITY_NEW_TASK: 效果类似singleTask。系统会为要启动的Activity寻找一个合适的任务栈(基于taskAffinity),如果找不到,就创建一个新的。 -
Intent.FLAG_ACTIVITY_CLEAR_TOP: 如果要启动的Activity实例已在当前任务栈中,则会清除它之上的所有Activity,使其位于栈顶。 -
黄金组合:
FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP- 当这两个标志组合使用时,其效果和
singleTask非常相似。如果目标Activity实例已存在,则会清除其上的Activity并复用,同时回调onNewIntent。这是在代码中动态实现“回到主页”等场景的常用手段。
- 当这两个标志组合使用时,其效果和
总结与建议
- 理解核心:掌握
LaunchMode的关键在于理解任务栈(Task)和taskAffinity。 - 关注细节:对于
singleTop,singleTask,singleInstance,重点关注onNewIntent回调和新Intent数据的处理。 - 系统性思考:不仅要了解静态的
LaunchMode,更要掌握动态的Intent Flags,并能说出它们之间的区别与联系,这能体现你知识的广度和深度。 - 场景驱动:为每种模式找到一个典型的应用场景,并能解释清楚为什么这个场景适合用该模式,解决了什么问题。