首页 / Android 入门教程 / 任务与返回栈

Android 入门教程

任务与返回栈

本教程共 100 篇 · 第 27 篇 · 更新于 2026-07-28 · 约 9 分钟阅读

AndroidAndroid 入门教程任务返回栈启动模式singleTopsingleTaskTask

27. 任务与返回栈

本节目标:理解任务(Task)和返回栈(Back Stack)是什么、四种启动模式各自的行为和适用场景,会根据需求选启动模式。

任务和返回栈是什么

任务(Task) 是用户完成某件事时交互的一组 Activity 集合。这些 Activity 按打开顺序排成返回栈(Back Stack)

生活化比喻:任务像一摞扑克牌,每打开一个 Activity 就往牌堆顶上加一张,按返回键就抽走最上面那张。后进先出(LIFO)。

栈顶:  Activity C(当前显示)
       Activity B
       Activity A(根 Activity,最先启动)
栈底

典型流程:

  1. 桌面点应用图标 -> 系统创建任务,主 Activity A 入栈。
  2. A 启动 B -> B 入栈顶,A 停止(界面保留)。
  3. B 启动 C -> C 入栈顶。
  4. 按返回 -> C 出栈销毁,B 恢复。
  5. 继续返回 -> B 出栈,A 恢复。
  6. 再返回 -> A 出栈,任务消失,回到桌面。

任务的生命周期

任务作为一个整体移动:

  • 按 Home 键:整个任务进后台(所有 Activity 停止),返回栈保留。
  • 从最近任务列表切回:任务回前台,栈顶 Activity 恢复,状态保留。
  • 启动新应用:原任务进后台,新应用起一个新任务。

所以用户切来切去时,每个应用的任务栈是独立保留的,能接着用。

Note
  • 任务里的 Activity 可能来自不同应用。比如你的应用调起相机 Activity 拍照,相机 Activity 进了你的任务栈。这叫「无缝协作」。

启动模式

默认情况下,每次 startActivity 都会创建新的 Activity 实例入栈。但有些场景你不想创建新实例—比如设置页已经打开了,再点设置应该回到原来的而不是开两个。

启动模式(launchMode)控制 Activity 实例怎么创建和入栈。有四种,在 Manifest 声明:

1. standard(默认)

每次启动都创建新实例,压入调用方的任务栈。

<activity android:name=".StandardActivity" />
<!-- 等价于 android:launchMode="standard" -->

适用:大部分场景。每次都是新界面。

2. singleTop

如果栈顶已经是该 Activity 实例,不创建新的,而是调它的 onNewIntent。否则创建新实例。

<activity android:name=".SingleTopActivity" android:launchMode="singleTop" />
当前栈: [A, B, C]
启动 C -> C 在栈顶,不新建,调 C.onNewIntent()
栈不变: [A, B, C]

启动 B -> B 不在栈顶,创建新 B
栈变成: [A, B, C, B']

适用:

  • 通知点击打开的 Activity(避免开一堆)。
  • 搜索页、设置页(已在前台时复用)。
Tip
  • singleTop 是最常用的非默认模式。适合「这个界面已经在最上面就别再开一个」的场景。

3. singleTask

整个系统里这个 Activity 只有一个实例。它所在的任务栈里,它之上不能有其他 Activity。

当前栈: [A, B, C]
启动 B(singleTask)
结果: B 之上的 C 被销毁,栈变成 [A, B],调 B.onNewIntent()

如果该 Activity 之前在别的任务栈里,系统会切到那个任务栈,把它上面的 Activity 清掉。

<activity android:name=".SingleTaskActivity" android:launchMode="singleTask" />

适用:

  • 应用主入口(如邮箱收件箱),保证回到唯一实例。
  • 想清掉之上所有界面的场景(如登录成功回到主页)。

4. singleInstance

跟 singleTask 类似,但这个 Activity 独占一个任务,整个系统只有一个实例,且它所在任务里只有它自己。

应用任务栈: [A, B]
启动 C(singleInstance)-> 系统新建任务 [C],C 独占
从 C 启动 D -> D 进应用原任务栈 [A, B, D],C 那个任务还是只有 C
<activity android:name=".SingleInstanceActivity" android:launchMode="singleInstance" />
Warning
  • singleInstance 很少用,行为复杂,容易导致导航混乱。除非有强需求(如全局拨号界面),别用。

用 Intent flags 临时控制

除了在 Manifest 声明启动模式,还能用 Intent 的 flag 临时改变行为:

val intent = Intent(this, MainActivity::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
}
startActivity(intent)

常用 flags:

Flag作用
FLAG_ACTIVITY_NEW_TASK在新任务里启动
FLAG_ACTIVITY_CLEAR_TOP如果目标已在栈里,清掉它上面的 Activity
FLAG_ACTIVITY_SINGLE_TOP等同 singleTop
FLAG_ACTIVITY_NO_HISTORY这个 Activity 不留在栈里,离开即销毁
FLAG_ACTIVITY_CLEAR_TASK启动时清空目标任务

经典场景:通知点击回到主页并清空栈:

val intent = Intent(context, MainActivity::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

taskAffinity:任务亲和性

taskAffinity 定义 Activity 「属于」哪个任务。默认是应用的包名。

<activity
    android:name=".SpecialActivity"
    android:taskAffinity="com.example.app.special" />

配合 FLAG_ACTIVITY_NEW_TASK 能让 Activity 启动到指定任务。日常很少改,知道有这个属性即可。

Compose 与返回栈

Compose 单 Activity 架构里,返回栈由 Navigation 组件管理,不是 Activity 任务栈:

NavHost(navController, startDestination = "home") {
    composable("home") { HomeScreen() }
    composable("detail") { DetailScreen() }
    composable("settings") { SettingsScreen() }
}

按返回键,Navigation 自动 popBackStack(),回到上一个 Composable。系统返回键集成由 BackHandler 处理:

@Composable
fun DetailScreen() {
    BackHandler {
        // 拦截返回键,做自定义逻辑
        showConfirmDialog()
    }
}
Note
  • Compose + Navigation 把「Activity 返回栈」简化成「Composable 导航栈」。日常不用操心 launchMode,除非涉及外部 Activity 调用。

常见场景与选择

场景推荐方案
普通页面跳转standard(默认)
通知点击打开主页singleTop + FLAG_ACTIVITY_CLEAR_TOP
登录成功回主页清栈Intent flags: NEW_TASK + CLEAR_TASK
全局唯一设置页singleTask
系统拨号、相机入口singleInstance(少用)
Compose 内部页面切换Navigation 组件,不用 Activity

小结

任务是 Activity 集合,按 LIFO 排成返回栈。四种启动模式:standard(默认新建)、singleTop(栈顶有则复用)、singleTask(全局唯一清上方)、singleInstance(独占任务,少用)。Intent flags 能临时控制。Compose 用 Navigation 组件管理自己的导航栈,返回键由 BackHandler 处理。下一节学 Activity 间数据传递。