启动模式 - intent

好的,我们来详细对比 singleTop 与其他三种标准启动模式(standard, singleTask, singleInstance)在 Intent 获取方式 以及 核心行为 上的区别。

核心区别在于:系统何时会创建新实例,何时会复用旧实例,以及复用时如何传递新的 Intent


1. standard (标准模式)

  • 行为:这是默认模式。每次启动该 Activity,系统都会创建一个新的实例,并将其压入启动它的 Activity 所在的任务栈(Task)中。可以有多个实例,也可以在不同任务栈中存在。
  • Intent 获取
    • 只在 onCreate() 中获取。因为每次都是新实例,所以新的 Intent 总是通过 onCreate(Bundle savedInstanceState) -> getIntent() 来获取。
    • onNewIntent() 永远不会被调用,因为没有复用旧实例的情况。
  • 适用场景:大多数常规 Activity,例如详情页、设置页等,每次打开都希望是独立的新页面。

2. singleTop (栈顶复用模式)

  • 行为:如果该 Activity 的实例已经位于目标任务栈的栈顶,则不会创建新实例,而是复用栈顶的这个实例。如果该实例存在但不在栈顶,或者根本不存在,则会创建新实例。
  • Intent 获取
    • 首次启动/不在栈顶时:通过 onCreate() -> getIntent() 获取。
    • 栈顶复用时:通过 onNewIntent(Intent newIntent) 获取,并必须onNewIntent 中调用 setIntent(newIntent) 来更新当前 Intent
  • 适用场景:通知栏点击、PendingIntent、或者防止用户快速连续点击导致创建多个相同 Activity 的场景。例如,一个消息列表页,点击通知希望直接跳转到该页并刷新数据,而不是在栈顶再叠一个相同的页面。

3. singleTask (栈内复用模式)

  • 行为:这是一种全局单例模式(在特定任务栈内)。系统会检查是否存在一个任务栈(由 taskAffinity 决定,默认是应用包名),该栈中是否已经存在该 Activity 的实例
    • 如果存在,则不会创建新实例。系统会将该实例之上的所有其他 Activity 全部出栈(销毁),使该 Activity 成为栈顶,然后复用这个实例
    • 如果不存在,则创建新实例,并根据 taskAffinity 决定放入哪个任务栈(可能是一个新栈)。
  • Intent 获取
    • 首次创建时:通过 onCreate() -> getIntent() 获取。
    • 复用时:通过 onNewIntent(Intent newIntent) 获取,并必须onNewIntent 中调用 setIntent(newIntent)
    • 关键副作用:复用时,目标 Activity 之上的所有 Activity 都会被 finish() 掉。
  • 适用场景:应用的**主入口 Activity**(如 Launcher Activity),确保从任何地方启动都能回到主界面并清理掉主界面之上的其他页面。也用于需要全局唯一且能清理回退栈的场景。

4. singleInstance (全局单例模式)

  • 行为:这是最严格的单例模式。该 Activity 只会存在一个实例,并且这个实例会独占一个全新的任务栈。任何应用启动这个 Activity,都会复用这个唯一的实例和它所在的任务栈。
    • 在这个独占栈中,只能有这一个 Activity 实例,其他 Activity 不能进入这个栈。
    • 如果这个 Activity 启动了其他 Activity,那个 Activity 会根据自己的启动模式和 taskAffinity 进入其他任务栈
  • Intent 获取
    • 首次创建时:通过 onCreate() -> getIntent() 获取。
    • 复用时:通过 onNewIntent(Intent newIntent) 获取,并必须onNewIntent 中调用 setIntent(newIntent)
  • 适用场景:非常少见。用于需要被多个应用共享的、完全独立的 Activity,比如系统级的闹钟提醒界面、全局悬浮窗控制器等。普通应用基本用不到。

总结对比表

启动模式 是否创建新实例 实例位置/任务栈 Intent 获取方式 onNewIntent 是否调用 主要适用场景
standard 总是创建新实例 启动者所在栈 onCreate() -> getIntent() 常规页面,如详情页
singleTop 仅当不在栈顶时创建新实例 启动者所在栈 onCreate()onNewIntent() (栈顶复用时) 通知点击、防止重复点击
singleTask 仅当栈内不存在时创建新实例 指定任务栈 (可能新建),全局单例 onCreate()onNewIntent() (栈内复用时) 主界面 (Launcher)
singleInstance 仅当全局不存在时创建新实例 独占一个全新任务栈,全局唯一 onCreate()onNewIntent() (全局复用时) 系统级共享页面 (极少使用)

关键记忆点

  • **standard**:最简单,每次都新,只用 onCreate
  • singleTop栈顶复用,用 onNewIntent不影响栈结构
  • singleTask栈内复用,用 onNewIntent会清空目标之上的Activity
  • singleInstance全局复用,用 onNewIntent独占一个栈

无论哪种模式,只要涉及复用旧实例(singleTop, singleTask, singleInstance),获取新数据的唯一可靠途径就是 onNewIntent(Intent intent),并且一定要记得调用 setIntent(intent)