Activity的四种启动方式
Activity的四种启动方式(LaunchMode)分别为 Standard,singleTop,singleTask,singleInstance。指定Activity的启动方式可以有两种方式;
1 在AndroidMainifset.xml 中指定:
<activity android:name=".SecondActivity"
android:launchMode="singleTop">
</activity>
2 在代码中指定
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
在代码中通过制定 intent 的flag来指定启动模式。该方式与在manifest文件中配置类似又不完全一一对应,后面我们会进行详细的说明。
可以将这四种启动模式分为两大类。第一类是 standard和singleTop,第二类是singleTask和singleInstance。
Activity的launchMode为 standard和singleTop的话,可以被多次实例化,并且加载到启动他的Activity所在的Activity栈当中。
而launchMode为singleTask和singleInstance的Activity只能属于一个栈,并且一般来说位于栈底(google api 文档原话:activities can only begin a task. They are always at the root of the activity stack. 但是这是不准确的,我们后续用实验来证明他是错误的)。并且每一个Activity仅能拥有一个实例。
下面就这四种启动模式,依次进行仔细的说明。
standard 模式
activity的默认启动模式,如果activity不配置android:launchMode,则默认为standard模式。
比如Activity的launchMode为standard,则每次启动Activity,都会创建Activity,并将其加入当前activity栈的顶端。
我们假设有A,B两个Activity,而他们的启动模式都是standard的,A启动B,B启动B,B启动A,A启动B,B启动A,A启动A,即A->B->B->A->B->A->A
那么这一连串的操作做完以后,当前任务栈中的Activity顺序为:
singleTop模式
考虑如下场景,Activity已经在栈顶,而现在因为一些原因Activity又被启动了一次,我们可能不希望栈顶的Activity能够被复用,而不是被再次创建Activity。这个时候,将launchMode设置为singleTop便可达成这样的效果。
当Activity的launchMode被设置为singleTop,如果该Activity在Activity栈的栈顶时,我们不再重新创建该Activity的实例,而是调用已存在的栈顶的Activity实例的onNewIntent函数将,其Intent参数正是我们re-launch该Activity时使用的intent。
举一个简单的例子。假设有A,B两个Activity,A为standard模式,而B为singleTop。按下面的顺序启动Activity,A->B->B->B->A->A->B
那么最后Activity栈中的Activity如下图所示。
当要被启动的Activity位于栈顶时,singleTop才发挥作用,不然和standard相同。
singleTask
顾名思义,在一task中,仅存在一份Activity实例。
启动带有launchMode为singleTask的Activity,我们可以分如下三种情况。
情况1. 如果该Activity所属的任务栈不存在(当然在这种情况下,该Activity也不存在),则创建该任务栈,创建该Activity并至于栈底。
情况2. 如果该任务栈已经存在,但是Activity不存在,那么创建Activity,加到该任务栈的最上方。
情况3. 如果栈和Activity都存在,那么将任务站上方的Activity都出栈,调用onNewIntent()方法。
注意这个概念,该Activity所属的任务栈:
Activity在manifest中可以配置属性taskaffinity,字面直译为任务亲和力,我个人认为是表明了该Activity所属的任务栈。实际上其值就是是一个字符串,表明该Activity将会启动在以该字符串命名的任务栈中。该属性默认值是包名,所以一般情况下,Activity启动在以包名命名的任务栈中。
假设Activity A和B在同一APK中,且的launchMode均为singleTask,B也为SingleTask,而他们的taskaffinity都不做配置,都为默认的包名。
那么假设他们的启动顺序是这样的,A->A->B->A->B
第一步启动A,符合上面描述的情况1
第二步启动A,符合上面描述的情况3
第三部启动B,符合上面描述的情况2
第三部启动A,符合上面描述的情况3
singleInstance
这是最强的一种启动模式,如果一个Activity被设置为singleInstance,那么说明该Activity位于一个独立的任务栈中,并且独占该任务栈,也就是说,该任务栈中有且仅有该Activity一个实例。
上面接单的介绍了四种启动模式,其中standard和singleTop是我们常用的launchMode,而singleTop和singleInstance相对少用。singleTop和singleInstace会使得我们的back stack变得与用户期望的行为有差异。所以在使用这两种模式之前,需要认识到这两种launch Mode的作用,以及对back stack的影响。
通过Intent Flag来设置启动模式
在AndroidManifeset.xml中配置launchMode表明了该Activity的属性,是自描述的,当我被别人启动的时候,我该以怎样的形式被别人启动。
而在Intent Flag中配置启动模式,则是启动方描述我期望以怎么样的行为来启动该Activity
与standard对应的是不设置启动模式
与singleTop对应的是FLAG_ACTIVITY_SINGLE_TOP
与singleTask对应的是FLAG_ACTIVITY_NEW_TASK
而singleInstance不存在对应的启动模式