Activity的四种launchMode
今天要讲的是 Activity 的四种 launchMode。launchMode 在多个 Activity 跳转过程中很重要:是否生成新实例、是否重用已存在实例、是否和其他实例共用一个 task。task 是具有栈结构的对象,一个 task 可以管理多个 Activity;启动一个应用,也就创建与之对应的 task。
Activity 一共有以下四种 launchMode:
-
standard -
singleTop -
singleTask -
singleInstance
在 AndroidManifest.xml 里把 android:launchMode 配成以上四种之一即可。下面结合实例一一介绍。
一、standard
standard 是默认启动模式,可以不配 android:launchMode,也可以显式指定为 standard。用名为 FirstActivity 的 Activity 演示。界面里的 TextView 显示当前实例序列号,Button 跳转到下一个 FirstActivity:
连续点击几次按钮,会出现下面的现象:



都是 FirstActivity 的实例,但序列号不同;需要连续按后退键两次,才能回到第一个 FirstActivity。standard 模式原理如下:

每次跳转系统都会在 task 中生成一个新的 FirstActivity 实例,放在栈顶;按后退才能看到原来的实例。这就是 standard:不管有没有已存在的实例,都生成新的实例。
二、singleTop
在上面基础上为 FirstActivity 指定 android:launchMode=”singleTop”,系统就会按 singleTop 处理跳转。重复上面几个动作,现象如下:



结果和 standard 不同:三个序列号相同,用的是同一个 FirstActivity 实例;按一下后退程序立即退出,说明栈里只有一个实例。singleTop 原理:

跳转时系统先看栈顶是否已有 FirstActivity 实例,有则不再生成新的,直接使用。如果栈里有多个 Activity、目标不在栈顶会怎样?再新建 SecondActivity:
把之前 FirstActivity 的跳转改成:
FirstActivity 跳到 SecondActivity,SecondActivity 再跳回 FirstActivity。演示结果:



两个 FirstActivity 的序列号不同,证明从 SecondActivity 跳回 FirstActivity 时生成了新实例。原理图:

从 SecondActivity 跳到 FirstActivity 时,系统发现存在 FirstActivity 实例,但不在栈顶,于是重新生成一个。这就是 singleTop:如果对应 Activity 实例正位于栈顶,则复用,不再生成新实例。
三、singleTask
在上面基础上把 FirstActivity 改成 android:launchMode=”singleTask”。演示结果:




过程中 FirstActivity 的序列号不变,SecondActivity 的序列号却不唯一:从 SecondActivity 跳到 FirstActivity 没有生成新实例,从 FirstActivity 跳到 SecondActivity 则生成了新实例。singleTask 原理图:

图下半部分是 SecondActivity 跳到 FirstActivity 后的栈变化:SecondActivity 消失了。系统发现已有 FirstActivity 实例,不再生成新的,而是把其上的 Activity 统统出栈,让 FirstActivity 变成栈顶、显示到幕前。
如果把 SecondActivity 也设为 singleTask,在本示例中其实无法保证它唯一:每次从 SecondActivity 跳到 FirstActivity,SecondActivity 都被迫出栈;下次 FirstActivity 再跳过来时找不到存在的实例,必须生成新的。但如果有 ThirdActivity,让 SecondActivity 和 ThirdActivity 互相跳转,SecondActivity 就可以保证唯一。
这就是 singleTask:如果发现有对应 Activity 实例,则使此实例之上的其他实例统统出栈,使它成为栈顶并显示到幕前。
四、singleInstance
这种模式比较特殊:会启用一个新的栈结构,把 Activity 放进去,并保证不再有其他 Activity 实例进入。把 FirstActivity 改回 launchMode=”standard”,SecondActivity 设为 singleInstance。因为涉及多个栈,需要在每个 Activity 里显示当前栈 id:
再演示这个流程:


这两个 Activity 实例分别被放在不同的栈结构中。singleInstance 原理图:

从 FirstActivity 跳到 SecondActivity 时,重新启用一个新栈来放 SecondActivity;按后退回到原始栈。图下半部分:在 SecondActivity 里再跳到 FirstActivity,系统会在原始栈里生成一个 FirstActivity 实例;然后回退两次并没有退出,而是回到了 SecondActivity——因为从 SecondActivity 跳出去时,起点变成了 SecondActivity 所在的栈,需要「回归」到这个栈。
如果把 FirstActivity 的 launchMode 改成 singleTop、singleTask、singleInstance 中的任意一个,流程将如图:

举个例子帮助理解:假如有一个 share 应用,ShareActivity 是入口、也是可供其他应用调用的 Activity,把它设为 singleInstance,然后在其他应用中调用。配置:
其他应用这样启动:
打开 ShareActivity 后再按后退回到原来界面时,ShareActivity 作为一个独立个体存在;这时再打开 share 应用,无需创建新实例即可看到结果,因为系统会查找,存在则直接利用。可以在 ShareActivity 里打印 taskId 看效果。过程原理图:

| launchMode | 是否新建实例 | 栈行为 |
|---|---|---|
| standard | 每次都新建 | 新实例入栈顶 |
| singleTop | 栈顶已有则复用 | 不在栈顶则仍新建 |
| singleTask | 任务栈里有则复用 | 其上实例全部出栈,使其到栈顶 |
| singleInstance | 单独占用一个栈 | 该栈里不允许再进其他 Activity |
原文出处:Activity 的四种 launchMode。
一句话总结:standard 总是新建;singleTop 只复用栈顶;singleTask 复用栈内实例并清掉它上面的页面;singleInstance 独占一个新栈。
转载请注明来源:Activity的四种launchMode







