一、Activity 启动模式(LaunchMode)和 Intent Flag 的区别
1. 启动模式(LaunchMode)
- 定义位置:在 AndroidManifest.xml 的 标签中通过 android:launchMode 属性设置。
- 作用范围:针对某个 Activity 的全局行为,决定该 Activity 被启动时在任务栈中的实例化和复用规则。
- 模式:
- standard(默认):每次启动都新建一个实例。
- singleTop:如果目标 Activity 已在栈顶,则复用栈顶实例,不新建。
- singleTask:如果目标 Activity 已在栈中,则复用该实例,并清除其上的所有 Activity。
- singleInstance:独占一个新的任务栈,且该栈只包含此 Activity 的实例。
2. Intent Flag
- 定义位置:在代码中通过 Intent 的 addFlags() 方法设置。
- 作用范围:只对本次启动 Activity 的行为生效(一次性),可以动态控制 Activity 的启动和栈管理。
- flags:
- FLAG_ACTIVITY_NEW_TASK
- FLAG_ACTIVITY_CLEAR_TOP
- FLAG_ACTIVITY_SINGLE_TOP
- FLAG_ACTIVITY_NO_HISTORY
- FLAG_ACTIVITY_CLEAR_TASK
- FLAG_ACTIVITY_MULTIPLE_TASK
二、两者的联系
- 都能影响 Activity 的启动和任务栈(Task Stack)行为。
- 部分 Intent flag 的行为与 Manifest 中的 launchMode 类似,但 flag 是临时的、可编程的,launchMode 是静态的、全局的。
- flag 可以覆盖 launchMode 的部分行为,比如通过 flag 可以让 standard 模式的 Activity 以 singleTask 的方式启动。
三、对应关系
launchMode | 对应Intent Flaog | 说明 |
---|---|---|
standard | 无 | 每次启动都新建实例。 |
singleTop | FLAG_ACTIVITY_SINGLE_TOP | 如果目标 Activity 已在栈顶,则复用,否则新建。 |
singleTask | FLAG_ACTIVITY_CLEAR_TOP + FLAG_ACTIVITY_SINGLE_TOP | 如果目标 Activity 已在栈中,清除其上的所有 Activity,并复用该实例。 |
singleInstance | FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_MULTIPLE_TASK | 独占一个新的任务栈。 |
注意:
- FLAG_ACTIVITY_NEW_TASK:如果 Activity 没有在 manifest 中声明为 singleTask 或 singleInstance,但用此 flag 启动,会在新的任务栈中启动该 Activity。
- FLAG_ACTIVITY_CLEAR_TOP:如果目标 Activity 已在栈中,清除其上的所有 Activity,并将目标 Activity 置于栈顶(会调用 onNewIntent)。
- FLAG_ACTIVITY_SINGLE_TOP:如果目标 Activity 已在栈顶,复用该实例(会调用 onNewIntent)。
四、适用场景
1. Manifest 中设置 launchMode 的适用场景
- 该 Activity 的启动行为是固定的、全局一致的,如主界面、登录页等。
- 需要保证 Activity 的唯一性或特殊栈管理,如:
- 主界面用 singleTask,避免重复实例。
- 独立的设置页用 singleInstance。
2. Intent Flag 的适用场景
- **需要临时改变 Activity 的启动行为,**如:
- 某些特殊跳转需要清空栈(如登录后清空之前的页面)。
- 动态控制 Activity 的栈管理(如通知栏点击跳转)。
- 不同场景下同一个 Activity 需要不同的启动方式。
五、实际开发建议
- launchMode 适合用于全局、固定的 Activity 启动策略。
- Intent flag 适合于临时、动态的启动需求。
- 两者可以结合使用,但要注意理解它们的优先级和相互影响。
- 实际开发中,建议优先用 launchMode 保证全局一致性,特殊需求用 flag 动态控制。
六、举例说明
- Manifest 设置 singleTask
<activity
android:name=".MainActivity"
android:launchMode="singleTask" />
无论怎么启动 MainActivity,始终只有一个实例,且在栈中只存在一份。
2. 代码中使用 flag
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
如果 MainActivity 已在栈中,清除其上的所有 Activity,并复用 MainActivity 实例。
3. 两者结合
Manifest 设置 standard,代码中根据需要动态添加 flag,灵活控制 Activity 的启动和栈管理。
七、几个问题
1. 只使用FLAG_ACTIVITY_CLEAR_TOP能达到singleTask的效果吗,为什么
不能,只使用 FLAG_ACTIVITY_CLEAR_TOP 不能完全达到 singleTask 的效果,,原因如下:
FLAG_ACTIVITY_CLEAR_TOP 的行为
- 当你用 FLAG_ACTIVITY_CLEAR_TOP 启动一个 Activity 时,如果该 Activity 已经在返回栈(Back Stack)中存在,系统会把它上面的所有 Activity 都清除掉,并把这个目标 Activity 重新置于栈顶。
- 如果目标 Activity 本身不是栈顶实例,系统会调用它的 onNewIntent() 方法,而不是重新创建实例。
- 如果目标 Activity 不在栈中,则会新建一个实例。
SingleTask 的行为
- 如果该 Activity 已经存在于某个任务栈中,系统会把它上面的所有 Activity 都清除,并调用它的 onNewIntent() 方法,不会新建实例。
- 如果不存在,则新建一个实例。
- 该 Activity 在同一个任务栈中始终只有一个实例。
差异分析
- 只用 FLAG_ACTIVITY_CLEAR_TOP 启动 standard 模式的 Activity,如果目标 Activity 已在栈中,确实会清除其上的 Activity,并复用该实例(调用 onNewIntent())。
- 但如果目标 Activity 此时正好在栈顶,FLAG_ACTIVITY_CLEAR_TOP 不会有任何作用,且会新建一个实例(standard 模式)。
- 而 singleTask 模式下,如果 Activity 已在栈顶,系统不会新建实例,而是直接复用(调用 onNewIntent())。
关键区别
- singleTask 保证了整个任务栈中始终只有一个该 Activity 的实例。
- FLAG_ACTIVITY_CLEAR_TOP 只是“清除目标 Activity 之上的所有 Activity”,但不能保证栈中只有一个目标 Activity 的实例(如果你多次以 standard 模式启动它,栈中可能有多个实例)。
- 推荐实践
- 需要全局唯一实例:用 singleTask。
- 只需临时清理栈上页面:用 FLAG_ACTIVITY_CLEAR_TOP。
2. FLAG_ACTIVITY_MULTIPLE_TASK的作用
允许为同一个 Activity 创建多个任务栈(Task)实例。
当与 FLAG_ACTIVITY_NEW_TASK 一起使用时,每次启动 Activity 都会创建一个全新的任务栈(Task),即使该 Activity 已经存在于其他任务栈中。这样可以在系统的“最近任务”列表(Recents)中看到同一个 Activity 的多个实例,每个实例在不同的任务(Task)中。
使用场景
- 需要让同一个 Activity 可以在不同的任务栈中多次存在,每个任务栈互不影响,比如浏览器,每打开一个网页都可以是一个新的任务栈,互不干扰。
- 多窗口、多任务体验(如 Android 7.0+ 的多窗口模式)。
使用方式
通常和 FLAG_ACTIVITY_NEW_TASK 搭配使用:
Intent intent = new Intent(this, MyActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);
- 仅使用 FLAG_ACTIVITY_NEW_TASK:如果目标 Activity 已经存在于某个任务栈中,会复用该任务栈,不会新建任务。
- 加上 FLAG_ACTIVITY_MULTIPLE_TASK 后,每次都会新建一个任务栈和 Activity 实例,不会复用已有的任务栈。
注意事项
- 该 flag 只对 standard 和 singleTop 启动模式的 Activity 有效。
- 对于 singleTask 和 singleInstance 启动模式的 Activity,系统会忽略此 flag。
- 滥用会导致系统中出现大量任务栈,影响用户体验和系统性能。
FLAG_ACTIVITY_MULTIPLE_TASK 允许同一个 Activity 在系统中以多个任务(Task)的形式并存,常与 FLAG_ACTIVITY_NEW_TASK 搭配使用,用于实现多实例、多任务的场景。