在 Android 中,Activity 的启动模式(Launch Mode) 决定了 Activity 实例如何与任务栈(Task Stack)交互,直接影响用户导航体验和资源管理。以下是 Kotlin 代码示例 和详细解析:
1. 四种启动模式
通过 AndroidManifest.xml
或 Intent Flags
配置。
(1) standard(默认模式)
- 行为:每次启动都会创建新实例,允许同一 Activity 多次存在于栈中。
- 适用场景:常规页面跳转(如新闻详情页)。
- 示例:xml
<activity android:name=".StandardActivity" android:launchMode="standard" />
kotlinval intent = Intent(this, StandardActivity::class.java) startActivity(intent) // 每次启动都会新建实例
(2) singleTop
- 行为:若目标 Activity 已处于栈顶,则复用该实例(调用
onNewIntent()
),否则新建实例。 - 适用场景:防止重复打开同一页面(如通知栏点击跳转)。
- 示例:xml
<activity android:name=".SingleTopActivity" android:launchMode="singleTop" />
kotlin// 在 SingleTopActivity 中处理复用逻辑 override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) // 更新数据(如刷新页面内容) }
(3) singleTask
- 行为:
- 在系统中全局唯一实例,位于独立的任务栈中。
- 若实例已存在,则清除其上的所有 Activity,并调用
onNewIntent()
。
- 适用场景:应用主界面(如首页),确保只存在一个实例。
- 示例:xml
<activity android:name=".MainActivity" android:launchMode="singleTask" android:taskAffinity="com.example.custom.task" /> <!-- 指定独立任务栈 -->
(4) singleInstance
- 行为:
- 类似
singleTask
,但独占一个任务栈,不允许其他 Activity 进入。 - 通常用于独立功能(如系统相机应用)。
- 类似
- 适用场景:与其他应用共享的独立功能(如支付页面)。
- 示例:xml
<activity android:name=".PaymentActivity" android:launchMode="singleInstance" />
2. Intent Flags(动态控制启动模式)
通过 Intent Flags
可以覆盖 Manifest 中的配置,更灵活地控制行为。
(1) 常用 Flags
Flag | 作用 |
---|---|
FLAG_ACTIVITY_NEW_TASK | 在新任务栈中启动 Activity(类似 singleTask ) |
FLAG_ACTIVITY_SINGLE_TOP | 等效于 singleTop 模式 |
FLAG_ACTIVITY_CLEAR_TOP | 若目标 Activity 已存在,清除其上的所有 Activity |
FLAG_ACTIVITY_CLEAR_TASK | 清空当前任务栈,新建 Activity 作为根 |
(2) 组合使用示例
kotlin
// 清空当前栈并跳转到登录页(类似“退出到登录”)
val intent = Intent(this, LoginActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
startActivity(intent)
3. 任务栈(Task Stack)管理
(1) 查看任务栈
通过 adb
命令查看当前任务栈:
bash
adb shell dumpsys activity activities
(2) 关键属性
taskAffinity
:定义 Activity 所属的任务栈(默认与包名相同)。xml<activity android:name=".SettingsActivity" android:taskAffinity="com.example.settings.task" />
allowTaskReparenting
:允许 Activity 在任务栈间迁移(如从浏览器打开应用内页面)。
4. 实际场景与解决方案
场景 1:避免登录页重复打开
- 方案:将登录页设为
singleTask
,确保全局唯一。xml<activity android:name=".LoginActivity" android:launchMode="singleTask" />
场景 2:从通知跳转到详情页并清空其他页面
- 方案:使用
FLAG_ACTIVITY_CLEAR_TOP
+FLAG_ACTIVITY_NEW_TASK
。kotlinval intent = Intent(context, DetailActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP } startActivity(intent)
场景 3:实现“退出应用”功能
- 方案:跳转到主页并清空栈。kotlin
val intent = Intent(this, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK } startActivity(intent) finish() // 结束当前 Activity
5. 常见问题
问题 1:onNewIntent()
不触发
- 原因:未正确设置
launchMode
或Intent Flags
。 - 解决:检查是否配置为
singleTop
或singleTask
,并在代码中处理onNewIntent()
。
问题 2:任务栈混乱
- 原因:错误使用
singleInstance
导致多个独立栈。 - 解决:优先使用
singleTask
,仅在绝对需要独占栈时使用singleInstance
。
总结
启动模式 | 特点 | 典型场景 |
---|---|---|
standard | 默认,允许多实例 | 普通页面跳转 |
singleTop | 栈顶复用 | 防止重复打开(如通知) |
singleTask | 全局唯一,清空上方 Activity | 首页、核心功能页 |
singleInstance | 独占任务栈 | 独立功能(如相机) |
合理选择启动模式可以优化用户体验,避免资源浪费和逻辑混乱。建议结合 ViewModel
和 SavedStateHandle
管理数据,确保生命周期与启动模式协同工作。