重新认识 Activity LaunchMode
做 Android 的同学想必对 activity 启动模式都不陌生,activity 有四种启动模式( standard
,singleTop
,singleTask
,singleInstance
),网上和一些书上也有各种讲解,但这些文章大多是针对四种启动模式进行介绍,总是在看过一段时间后就忘掉了。本文希望带你重新理解 activity 启动模式,并理解一些其他的相关概念,而不是仅仅针对四种启动模式。
1. 从 Task 说起
Activity 启动模式是与 task 密切相关的,所以我们先从 task 说起。
A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the back stack), in the order in which each activity is opened.
上面这句话是官方文档里的,解释了 Android 中 task 的概念,task 就是若干 activity 组成的一个集合,以栈的形式来管理。在 Android 中,每个 activity 都是运行在 task 中的,前台 task 的栈顶 activity 位于前台,可以直接与用户交互。
那么一个 activity 运行在哪个 task 中是由谁来决定的呢?我们首先来看 taskAffinity,taskAffinity 是影响 Activity 运行在哪个 task 中的第一个因素。
一个 activity 的 taskAffinity 是我们在 manifests.xml
里定义的,每个 Activity 都可以设置一个 android:taskAffinity
属性,它的值是一个字符串。application
元素也有这个属性,它的默认值是 manifest
元素中指定的包名(package
属性)。对于 Activity 的这个属性,当我们不显式设置的时候它就会从 application
元素继承。
那么在 taskAffinity 属性起作用的情况下,除了 taskAffinity 值为空字符串的 Activity,具有相同 taskAffinity 的 Activity 会运行在同一个 task 中,即使它们处于不同的应用中。taskAffinity 为空字符串表示这个 Activity 不会与其他任何 task 关联。
2. manifests.xml
中的 launchMode
我们可以在 manifests.xml
中为 activity 指定 android:launchMode
属性,可以的取值有 standard
,singleTop
,singleTask
,singleInstance
,默认值是 standard
。
那么我们不设置 Intent flags(下文会讲到)的情况下启动一个 activity 的时候,系统就会根据 manifests.xml
里设置的 launchMode 来决定 activity 启动模式。下面是四种启动模式的处理说明。
standard
,singleTop
:在当前 task 中启动,忽略 taskAffinity 属性。
两种模式的区别是standard
模式每次启动都会创建新的实例,而singleTop
模式则是若已经有该 activity 的实例存在于 task 栈顶的情况下不再创建新实例,而是回调该实例的onNewIntent()
方法。singleTask
:这时该 activity 要在哪个 task 中运行就由我们前面指定的 taskAffinity 来决定了(该 activity 只能运行在 taskAffinity 与自己的 taskAffinity 相同的 task 中)。并且在这个 task 中该 activity 的实例只允许存在一个,若已经有一个实例在栈顶,就会回调它的onNewIntent()
方法;若有实例且不在栈顶,系统则会将该 task 中该位于该实例之上的 activity 出栈销毁,使该实例回到前台,并回调其onNewIntent()
方法。singleInstance
:与singleTask
类似,区别在于singleInstance
的 task 中只能有一个 activity 实例存在,即该 activity 只能单独运行于一个 task 中。
3. Intent flag
影响 activity 启动模式的另一个地方就是 Intent flag 了。我们可以在使用 Intent 启动一个 activity 的时候可以调用 Intent 的 setFlag()
方法来为它设置标志位,且 Intent flag 具有更高的优先级。影响 activity 启动模式的 Intent flag 有下面几个。
FLAG_ACTIVITY_NEW_TASK
:在新 task 中启动 activity,效果与singleTask
模式类似,但不会清除目标 activity 之上的 activity。使用这个 flag 可以实现应用间切换的效果。FLAG_ACTIVITY_SINGLE_TOP
:与singleTop
模式效果相同。FLAG_ACTIVITY_CLEAR_TOP
:若目标 activity 在其 task 中已经有实例存在,则将 task 中其上的 activity 出栈销毁,使该实例回到前台,并回调其onNewIntent()
方法。与FLAG_ACTIVITY_NEW_TASK
结合使用可以实现singleTask
模式的效果。