深度解析Android Activity启动模式:从生命周期到任务栈管理

149 阅读4分钟

一句话总结:

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且已在栈顶) :

    1. 当再次尝试启动B时,B会经历 onPause() -> onNewIntent() -> onResume()
    2. 关键点: 在onNewIntent(intent)里,必须调用setIntent(intent),否则后续getIntent()获取的仍是旧的Intent数据。

3. singleTask (栈内单例模式)

启动时,系统会先寻找是否存在一个与该Activity的taskAffinity(任务亲和性)属性匹配的任务栈。

  • 如果存在这样的栈:

    • 检查栈内是否有该Activity的实例。如果有,则将它上面的所有其他Activity全部出栈(执行onDestroy),使该实例回到栈顶,并调用其onNewIntent()
    • 如果没有实例,则在该栈顶部创建新实例。
  • 如果不存在这样的栈:

    • 创建一个新的任务栈(其taskAffinity与该Activity匹配),然后将该Activity作为根Activity压入新栈。
  • 应用场景: 应用的主界面(如微信主页)、浏览器主页。确保应用的核心入口只有一个,并且返回时能清掉中间页面,直接回到主页。

  • 生命周期细节 (栈: A -> B -> C, 此时启动A) :

    1. C和B会依次执行onPause -> onStop -> onDestroy,被销毁出栈。
    2. A会回调onNewIntent来接收新的启动意图,然后是onRestart -> onStart -> onResume

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,并能说出它们之间的区别与联系,这能体现你知识的广度和深度。
  • 场景驱动:为每种模式找到一个典型的应用场景,并能解释清楚为什么这个场景适合用该模式,解决了什么问题。