Skip to content

在 Android 中,Activity 的启动模式(Launch Mode) 决定了 Activity 实例如何与任务栈(Task Stack)交互,直接影响用户导航体验和资源管理。以下是 Kotlin 代码示例 和详细解析:


1. 四种启动模式

通过 AndroidManifest.xmlIntent Flags 配置。

(1) standard(默认模式)

  • 行为:每次启动都会创建新实例,允许同一 Activity 多次存在于栈中
  • 适用场景:常规页面跳转(如新闻详情页)。
  • 示例
    xml
    <activity android:name=".StandardActivity" android:launchMode="standard" />
    kotlin
    val 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
    kotlin
    val 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() 不触发

  • 原因:未正确设置 launchModeIntent Flags
  • 解决:检查是否配置为 singleTopsingleTask,并在代码中处理 onNewIntent()

问题 2:任务栈混乱

  • 原因:错误使用 singleInstance 导致多个独立栈。
  • 解决:优先使用 singleTask,仅在绝对需要独占栈时使用 singleInstance

总结

启动模式特点典型场景
standard默认,允许多实例普通页面跳转
singleTop栈顶复用防止重复打开(如通知)
singleTask全局唯一,清空上方 Activity首页、核心功能页
singleInstance独占任务栈独立功能(如相机)

合理选择启动模式可以优化用户体验,避免资源浪费和逻辑混乱。建议结合 ViewModelSavedStateHandle 管理数据,确保生命周期与启动模式协同工作。