Activity的五种启动模式的具体使用场景详解

下面把 Activity 五种启动模式按"适用场景 → 典型搭配 → 返回栈行为 → 代码示例 → 易错点"讲清楚;最后给一张选型对照表与决策建议。

(五种=standard、singleTop、singleTask、singleInstance、singleInstancePerTask〔Android 12+〕)


1)standard(默认,能多开)

适用场景

  • 常规页面:详情页、设置子页、搜索结果页等。

  • 同一路由可允许多个实例并存(如 A→详情(1)→详情(2)...)。

常配 flags

  • 默认无;需要切栈/新任务时才加 FLAG_ACTIVITY_NEW_TASK(少见于单进程 App)。

  • 返回栈按"谁先开谁后退"。

示例

ini 复制代码
<activity android:name=".ui.DetailActivity" android:launchMode="standard"/>
kotlin 复制代码
startActivity(Intent(this, DetailActivity::class.java)
  .putExtra("id", 123L))

易错点

  • 误以为返回时会"合并同类项",不会;每次 startActivity 都是新实例。

2)singleTop(顶复用,不顶就新建)

适用场景

  • 通知点进的"唯一入口页"(消息中心、会话页)------若已在栈顶,直接复用,避免"连点生成一串重复页面"。

  • 顶部 Tab 容器/Home:从 Deep Link/通知再次进入时不重建,而是 onNewIntent() 刷新内容。

常配 flags

  • FLAG_ACTIVITY_SINGLE_TOP(等价 Manifest 写 singleTop)。
  • 常与 FLAG_ACTIVITY_CLEAR_TOP同用:若目标页已在栈内但不在顶,则清掉它上面的页面再复用它。
less 复制代码
startActivity(Intent(this, HomeActivity::class.java)
  .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
  .putExtra("tab", "inbox"))

返回栈

  • 若目标已是栈顶→不建新实例,走 onNewIntent();否则新建并入栈。

易错点

  • singleTop 只在"目标位于栈顶"时复用;不在顶仍会新建。想"清到它并复用",记得加 CLEAR_TOP。

3)singleTask(任务级唯一,清到它 + 复用)

适用场景

  • 全局任务入口/外壳页:如 MainActivity、路由中转页、认证后回到唯一主页的场景。

  • 从外部唤起(Deep Link / 分享回流 / 第三方跳转)但希望"回到已有任务的入口并清理中间页"。

常配 flags / 属性

  • Manifest 直接写 singleTask;必要时配 taskAffinity 将其固定在某个 task。

  • 代码侧常见 Intent.FLAG_ACTIVITY_NEW_TASK(跨进程/服务启动时),系统会把已有实例的 task 前置 并 onNewIntent(),同时把它上面的页面清掉

返回栈

  • 已存在实例→把该 task 前置,清栈到它,并回调 onNewIntent()。

  • 不存在实例→新建一个以它为根的 task。

示例

ini 复制代码
<activity
    android:name=".ui.MainActivity"
    android:launchMode="singleTask"
    android:exported="true"/>

易错点

  • 二次进入会"清到它",上面的页面会被移除;不适合用于需要"多层历史可回退"的页面。

4)singleInstance(独占一栈,全局仅一实例)

适用场景(非常少用)

  • 来电界面、锁屏器、系统级浮层场景:这一个 Activity 必须独占一个任务栈,栈里不能再有别的页面。

  • 从它再 startActivity(),新页面会被放到另一个 task。普通 App 几乎不需要。

返回栈

  • 只有它自己;切走/返回会在不同任务间切换。

示例

ini 复制代码
<activity android:name=".ui.InCallActivity"
          android:launchMode="singleInstance"
          android:showOnLockScreen="true"
          android:turnScreenOn="true"/>

易错点

  • 用户体验割裂、跨任务切换多;除非强需求,不建议业务页使用。

5)singleInstancePerTask(Android 12+,每个任务栈最多一个该 Activity)

适用场景

  • 多窗口/多文档 :同一路由可在不同 task 各有一个实例(比如"文档A"和"文档B"分别在两个任务里),但单个 task 内不会重复

  • 适合需要"每个任务的根页面唯一"的多任务产品设计。

返回栈

  • 各自的 task里做根;再次打开相同文档/会话时复用对应 task 的该实例并 onNewIntent();不同文档可开到新 task。

示例

ini 复制代码
<activity android:name=".ui.EditorActivity"
          android:launchMode="singleInstancePerTask"
          android:exported="true"/>

易错点

  • 与旧的 singleInstance 不同:不是"全局唯一",而是"每个任务栈唯一"。

典型业务场景配方

A. 通知点击 → 回到唯一主页并刷新

  • MainActivity:singleTop 或 singleTask

  • Intent:CLEAR_TOP | SINGLE_TOP(或直接 singleTask)

  • 逻辑:在 onNewIntent() 解析 extras,切换 Tab/滚到锚点。

B. Deep Link(https App Links)→ 若已在前台则复用主页

  • Manifest:主页 singleTop(常见)/singleTask(需要清栈到主页时)。

  • 链接命中后系统把 Intent 投递到 onNewIntent(),你解析路径路由到目标子页。

C. 登录完成后"回到首页并清理登录链路"

  • 登录成功时 startActivity(MainActivity, flags=CLEAR_TOP|SINGLE_TOP),或者把 Main 设为 singleTask 并 startActivity(Main);

  • 效果:清除登录过程页面,避免返回键又回到登录页。

D. 同一路由允许打开多个详情(从列表连续点击不同 item)

  • 详情 Activity:用 standard;每次点击即新建,返回键逐个退出。

E. 多文档/多会话分别驻留不同任务(Android 12+)

  • 编辑器/会话页:singleInstancePerTask;配合 FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK 按需创建新任务。

代码模板(组合常用)

singleTop + 清到它:

kotlin 复制代码
fun Context.toHome(tab: String? = null) {
    startActivity(Intent(this, HomeActivity::class.java).apply {
        addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
        putExtra("tab", tab)
    })
}

singleTask 主页(外部唤起/清栈回家):

ini 复制代码
<activity android:name=".ui.MainActivity"
          android:launchMode="singleTask"
          android:exported="true"/>
kotlin 复制代码
startActivity(Intent(this, MainActivity::class.java)
  .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) // 服务/广播里启动时常用

多文档(12+):

ini 复制代码
<activity android:name=".ui.EditorActivity"
          android:launchMode="singleInstancePerTask"/>
kotlin 复制代码
startActivity(Intent(this, EditorActivity::class.java).apply {
    action = Intent.ACTION_VIEW
    data = uri // 每个文档一个 task
    addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
})

常见坑与验证要点

  • onNewIntent() 不是生命周期重建:UI 需自己刷新(比如 Compose 用 mutableStateOf 承接新的参数)。
  • CLEAR_TOP 行为:清除目标之上的页面;若目标为 singleTop,复用并触发 onNewIntent()。
  • taskAffinity 不会单独造新任务 :是否新建取决于 launchMode/flags,taskAffinity 只决定"更偏向放进哪个 task"。
  • 返回键逻辑 :变更 launchMode/flags 会改变 back stack,务必写出"期望的返回路径"用例并实机点按
  • 通知/Deep Link:优先让"容器/主页"具备 singleTop,避免重复页面;在 onNewIntent() 做路由。

选型对照(速览)

模式 复用条件 是否可多实例 常见用途 典型 flags
standard 不复用 是(同 task 多个) 普通详情/子页 (无)
singleTop 目标已在栈顶 视情况 通知入口、首页容器 `CLEAR_TOP
singleTask 任务内唯一,清到它 任务级唯一 全局入口/外壳、回主页 NEW_TASK(跨进程)
singleInstance 全局唯一,独占一栈 来电/锁屏等系统场景 (谨慎使用)
singleInstancePerTask 每个 task 一个 跨 task 可多个 多文档/多窗口 `NEW_DOCUMENT

实战建议(结论)

  • 90% 的页面 → standard。
  • 主页/容器 → singleTop(+必要时 CLEAR_TOP),需要"回家清栈"则考虑 singleTask。
  • 系统级特殊页面才用 singleInstance。
  • 需要多文档/多任务体验(12+)→ singleInstancePerTask 配 NEW_DOCUMENT。
相关推荐
疯狂踩坑人3 小时前
【面试系列】万字长文,速通TCP、HTTP(s)、DNS、CDN、websocket、SSE
前端·面试
小时前端3 小时前
前端稳定性:你的应用经得起一场“混沌演练”吗?
前端·面试
绝无仅有5 小时前
某短视频大厂的真实面试解析与总结(一)
后端·面试·github
JavaGuide5 小时前
中兴开奖了,拿到了SSP!
后端·面试
绝无仅有5 小时前
腾讯MySQL面试深度解析:索引、事务与高可用实践 (二)
后端·面试·github
沐怡旸19 小时前
【穿越Effective C++】条款7:为多态基类声明virtual析构函数——C++多态资源管理的基石
c++·面试
Achieve前端实验室20 小时前
【每日一面】async/await 的原理
前端·javascript·面试