Activity启动模式二

上篇文章Activity启动模式一主要介绍了Activity的四种启动模式,这些启动模式都是在AndroidManifest中进行配置的。除此以外,Android系统还经过Intent类提供了一些标志位,一样能够指定Activity的启动模式。本文将介绍下这些和Activity启动相关的标志位。java

通常状况下,咱们在启动目标Activity的Intent中指定这些标志位,以下所示:android

Intent intent = new Intent();
intent.setClass(MainActivity.this,FirstActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
复制代码

当同时在配置文件中指定launchMode和在Intent中指定上面的标志位时,以标志位为准,即代码的优先级比AndroidManifest的优先级更高!测试

下面咱们经过具体案例看下和Activity启动相关的4种标志位:this

Activity启动相关的四种标志位

FLAG_ACTIVITY_NEW_TASK

官方文档上介绍该标志位和SingleTask启动模式具备相同效果,其实否则。应该是FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP一块儿等同于SingleTask启动模式。spa

这里咱们经过4个案例,看下单独使用FLAG_ACTIVITY_NEW_TASK标志位和一块儿使用FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_CLEAR_TOP标志位的具体效果。3d

案例1

两个Activity的taskAffinity属性相同,具体步骤以下所示:code

  1. 建立MainActivity和FirstActivity,且二者的启动模式都是Standard,TaskAffinity也相同。
  2. 首先启动MainActivity,接着经过MainActivity启动FirstActivity,而后再经过FirstActivity启动MainActivity,如此反复。
  3. 启动FirstActivity的Intent中指定了FLAG_ACTIVITY_NEW_TASK标志位,启动MainActivity的Intent不包含任何标志位。

通过MainActivity -> FirstActivity -> MainActivity后,最终的任务栈以下所示: cdn

new_task-taskAffinity相同-1
可见,由于两个Activity的taskAffinity属性相同,因此第一次启动FirstActivity时并无建立新的任务栈。

最后,MainActivity再次启动FirstActivity后,最终的任务栈以下所示: blog

new_task-taskAffinity相同-2
由于只有FLAG_ACTIVITY_NEW_TASK标志位,没有FLAG_ACTIVITY_CLEAR_TOP,因此没法清除FirstActivity之上的MainActivity,复用已有FirstActivity。而是建立了新的FirstActivity。

经过上面的任务栈可知:在taskAffinity相同的状况下,单独添加FLAG_ACTIVITY_NEW_TASK不起任何做用。文档

案例2

两个Activity的taskAffinity属性不相同,具体步骤以下所示:

  1. 建立MainActivity和FirstActivity,且二者的启动模式都是Standard,可是TaskAffinity不一样。
  2. 首先启动MainActivity,接着经过MainActivity启动FirstActivity,而后再经过FirstActivity启动MainActivity,如此反复。
  3. 启动FirstActivity的Intent中指定了FLAG_ACTIVITY_NEW_TASK标志位,启动MainActivity的Intent不包含任何标志位。

通过MainActivity -> FirstActivity -> MainActivity后,最终的任务栈以下所示:

new_task-taskAffinity不一样-1
可见,由于两个Activity的taskAffinity属性不一样,因此第一次启动FirstActivity时,建立了新的任务栈(TaskId为1979).

最后,MainActivity再次启动FirstActivity后,最终的任务栈以下所示:

new_task-taskAffinity不一样-2
能够看到,任务栈没有发生任何变化,也没有建立新的FirstActivity实例。这是由于FirstActivity实例已经存在于它所指望的任务栈中,而单独添加FLAG_ACTIVITY_NEW_TASK标志位又不会清除任务栈中位于FirstActivity之上的Activity实例,因此就没有发生跳转。

经过上面的任务栈可知:在taskAffinity不一样的状况下,第一次启动FirstActivity时,会新建一个任务栈,并将FirstActivity实例添加到该task中。这与SingleTask启动模式产生的效果是一致的。可是,当企图再次从MainActivity进入到FirstActivity时,却什么也没有发生,缘由上面已经说明了。

综上所述,单独使用FLAG_ACTIVITY_NEW_TASK会产生很是奇怪的行为,所以通常和FLAG_ACTIVITY_CLEAR_TOP标志位一块儿使用,这样能够实现相似SingleTask的效果,可是不彻底相同,下面会进行介绍。

下面咱们再经过两个案例看下FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP一块儿使用的效果。

案例3

两个Activity的taskAffinity属性相同,具体步骤以下所示:

  1. 建立MainActivity和FirstActivity,且二者的启动模式都是Standard,TaskAffinity也相同。
  2. 首先启动MainActivity,接着经过MainActivity启动FirstActivity,而后再经过FirstActivity启动MainActivity,如此反复。
  3. 启动FirstActivity的Intent中指定了FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP标志位,启动MainActivity的Intent不包含任何标志位.

通过MainActivity -> FirstActivity -> MainActivity后,最终的任务栈以下所示:

new_task-clear_top-taskAffinity相同-1
可见,由于两个Activity的taskAffinity属性相同,因此第一次启动FirstActivity时并无建立新的任务栈。

最后,MainActivity再次启动FirstActivity后,最终的任务栈以下所示:

new_task-clear_top-taskAffinity相同-2
貌似是和SingTask启动模式的效果相同,可是细看一下就会发现区别: 先后两次FirstActivity实例是不一样的,也就是没有复用第一次启动的FirstActivity,而是清除了FirstActivity及其之上的全部Activity,而后新建FirstActivity实例添加到了当前任务栈

经过上面的任务栈可知:在taskAffinity相同的状况下,FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP标志位组合确实不会建立新的任务栈,可是会清除了FirstActivity及其之上的全部Activity,并新建FirstActivity实例添加到了当前任务栈,这点是和SingleTask模式的差别。(SingleTask仅会清除FirstActivity之上的Activity,而后复用已有的FirstActivity)

案例4

两个Activity的taskAffinity属性不相同,具体步骤以下所示:

  1. 建立MainActivity和FirstActivity,且二者的启动模式都是Standard,可是TaskAffinity不一样。
  2. 首先启动MainActivity,接着经过MainActivity启动FirstActivity,而后再经过FirstActivity启动MainActivity,如此反复。
  3. 启动FirstActivity的Intent中指定了FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP标志位,启动MainActivity的Intent不包含任何标志位。

通过MainActivity -> FirstActivity -> MainActivity后,最终的任务栈以下所示:

new_task-clear_top-taskAffinity不一样-1
可见,由于两个Activity的taskAffinity属性不一样,因此第一次启动FirstActivity时,建立了新的任务栈(TaskId为1980).

最后,MainActivity再次启动FirstActivity后,最终的任务栈以下所示:

new_task-clear_top-taskAffinity不一样-2
能够看到,和案例3 taskAffinity属性相同的状况相似(除了建立了新的任务栈),直接清除了FirstActivity及其之上的全部Activity,而后建立新的FirstActivity实例添加到新的任务栈(TaskId为1980)。

经过上面的任务栈可知:在taskAffinity不一样的状况下,FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP标志位组合会为首次启动的FirstActivity建立新的任务栈,其余的逻辑与案例3基本相同,都是直接清除了FirstActivity及其之上的全部Activity,而后建立新的FirstActivity实例,这也是和SingleTask模式的区别

综上所述,FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP标志位组合产生的效果整体上和SingleTask模式相同,除了不会复用FirstActivity实例以外。

FLAG_ACTIVITY_CLEAR_TOP

该标志位在上面已经使用过了,做用是清除包含目标Activity的任务栈中位于该Activity实例之上的其余Activity实例。可是是复用已有的目标Activity,仍是像上面那样先删除后重建,则有如下规则:

  1. 如果单独使用FLAG_ACTIVITY_CLEAR_TOP,那么只有非Standard启动模式的目标Activity才会被复用,其余启动模式的目标Activity都先被删除,而后被从新建立并入栈。
  2. 如果使用FLAG_ACTIVITY_SINGLE_TOP和FLAG_ACTIVITY_CLEAR_TOP标志位组合,那么无论目标Activity是什么启动模式,都会被复用。

由于上面的案例3和案例4都不符合上面的两条规则,因此FirstActivity才会先被清除,而后重建。

下面咱们经过几个具体案例,验证下上面的两条规则:

案例1

具体步骤以下所示:

  1. 建立MainActivity和FirstActivity,且二者的启动模式都是Standard。
  2. 首先启动MainActivity,接着经过MainActivity启动FirstActivity,而后再经过FirstActivity启动MainActivity,如此反复。
  3. 启动FirstActivity的Intent中指定了FLAG_ACTIVITY_CLEAR_TOP标志位,启动MainActivity的Intent不包含任何标志位。

通过MainActivity -> FirstActivity -> MainActivity后,最终的任务栈以下所示:

clear_top-standard-1

最后,MainActivity再次启动FirstActivity后,最终的任务栈以下所示:

clear_top-standard-2

经过上面的任务栈可知:第二次MainActivity -> FirstActivity时,会先把FirstActivity以及之上的Activity所有销毁,而后建立新的FirstActivity入栈,正符合咱们的预期。

案例2

具体步骤以下所示:

  1. 建立MainActivity和FirstActivity,MainActivity的启动模式是Standard,FirstActivity的启动模式是SingleTop。
  2. 首先启动MainActivity,接着经过MainActivity启动FirstActivity,而后再经过FirstActivity启动MainActivity,如此反复。
  3. 启动FirstActivity的Intent中指定了FLAG_ACTIVITY_CLEAR_TOP标志位,启动MainActivity的Intent不包含任何标志位。

通过MainActivity -> FirstActivity -> MainActivity后,最终的任务栈以下所示:

clear_top-SingleTop-1

最后,MainActivity再次启动FirstActivity后,最终的任务栈以下所示:

clear_top-SingleTop-2

经过上面的任务栈可知:第二次MainActivity -> FirstActivity时,会先把FirstActivity之上的Activity所有销毁,而后复用已有的FirstActivity实例,也符合咱们的预期。


此外,当FirstActivity是SingleTask和SingleInstance模式时,其效果和SingleTop启动模式同样,也是首先销毁FirstActivity之上的全部Activity,而后复用已有的FirstActivity实例。

这里仅给出我验证的任务栈: 当FirstActivity是SingleTask模式时(taskAffinity相同),通过MainActivity -> FirstActivity -> MainActivity后,最终的任务栈以下所示:

clear_top-SingleTask-1

最后,MainActivity再次启动FirstActivity后,最终的任务栈以下所示:

clear_top-SingleTask-2
可见,确实复用了已有的FirstActivity实例。

当FirstActivity是SingleInstance模式时,通过MainActivity -> FirstActivity -> MainActivity后,最终的任务栈以下所示:

clear_top-SingleInstance-1

最后,MainActivity再次启动FirstActivity后,最终的任务栈以下所示:

clear_top-SingleInstance-2
可见,确实复用了已有的FirstActivity实例。

综上所述,经过案例1和案例2,咱们验证了规则1是OK的。 下面咱们继续验证下规则2:

案例3

具体步骤以下所示:

  1. 建立MainActivity和FirstActivity,且二者的启动模式都是Standard。
  2. 首先启动MainActivity,接着经过MainActivity启动FirstActivity,而后再经过FirstActivity启动MainActivity,如此反复。
  3. 启动FirstActivity的Intent中指定了FLAG_ACTIVITY_SINGLE_TOP + FLAG_ACTIVITY_CLEAR_TOP标志位,启动MainActivity的Intent不包含任何标志位。

通过MainActivity -> FirstActivity -> MainActivity后,最终的任务栈以下所示:

single_top-clear_top-1

最后,MainActivity再次启动FirstActivity后,最终的任务栈以下所示:

single_top-clear_top-2

经过上面的任务栈可知:第二次MainActivity -> FirstActivity时,会先把FirstActivity之上的Activity所有销毁,而后复用已有的FirstActivity实例,也符合咱们的预期。

综上所述,既然在FLAG_ACTIVITY_SINGLE_TOP + FLAG_ACTIVITY_CLEAR_TOP标志位组合的状况下,Standard模式的FirstActivity都已经被复用了,那么其余启动模式的Activity也必然会被复用。(单独使用FLAG_ACTIVITY_CLEAR_TOP都会被复用,况且又添加了FLAG_ACTIVITY_SINGLE_TOP标志位,经过Demo验证也确实如此,就再也不给出具体案例了)。

综上所述,上面的两条规则还要是遵照的^_^。

FLAG_ACTIVITY_CLEAR_TASK

该标志位通常和FLAG_ACTIVITY_CLEAR_TASK一块儿使用,目的是启动目标Activity时,首先清空已经存在的目标Activity实例所在的任务栈,这天然也就清除了以前存在的目标Activity实例,而后建立新的目标Activity实例并入栈。

通过Demo测试发现,单独使用FLAG_ACTIVITY_CLEAR_TASK标志位,无论taskAffinity是否相同,都不会产生什么效果。例以下面是单独使用该标志位的最终任务栈(taskAffinity相同 or 不一样都是这样):

clear_task
感兴趣的能够自行尝试,这里再也不赘述。

下面看下FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK标志位组合在taskAffinity相同 and 不一样的状况下的效果。

案例1

两个Activity的taskAffinity属性相同,具体步骤以下所示:

  1. 建立MainActivity和FirstActivity,且二者的启动模式都是Standard,taskAffinity也相同
  2. 首先启动MainActivity,接着经过MainActivity启动FirstActivity,而后再经过FirstActivity启动MainActivity,如此反复。
  3. 启动FirstActivity的Intent中指定了FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK标志位,启动MainActivity的Intent不包含任何标志位。

第一次启动MainActivity后,任务栈以下所示:

new_task-clear_task-1

接着MainActivity启动FirstActivity后,任务栈以下所示:

new_task-clear_task-2
首先启动的MainActivity竟然被清除了,而后才建立了FirstActivity实例。

而后FirstActivity启动MainActivity后,任务栈以下所示:

new_task-clear_task-3

最后MainActivity再次启动FirstActivity后,任务栈以下所示:

new_task-clear_task-4
可见,系统再次清除了FirstActivity及其之上的MainActivity,而后从新建立了新的FirstActivity实例并入栈。

经过上面的任务栈可知:当经过FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK标志位组合启动FirstActivity时,首先会清空FirstActivity所在的任务栈,而后再建立新的FirstActivity实例并入栈

案例2

两个Activity的taskAffinity属性不相同,具体步骤以下所示:

  1. 建立MainActivity和FirstActivity,且二者的启动模式都是Standard,taskAffinity不相同
  2. 首先启动MainActivity,接着经过MainActivity启动FirstActivity,而后再经过FirstActivity启动MainActivity,如此反复。
  3. 启动FirstActivity的Intent中指定了FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK标志位,启动MainActivity的Intent不包含任何标志位。

第一次MainActivity启动FirstActivity后,任务栈以下所示:

new_task-clear_task-5
由于taskAffinity不一样,因此为FirstActivity实例建立了新的任务栈。

而后FirstActivity启动MainActivity后,任务栈以下所示:

new_task-clear_task-6

最后MainActivity再次启动FirstActivity后,任务栈以下所示:

new_task-clear_task-7
可见,系统首先清除了任务栈(TaskId为2040)中FirstActivity及其之上的MainActivity,而后从新建立了新的FirstActivity实例并入栈(TaskId为2040)。

经过上面的任务栈可知:当经过FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK标志位组合启动FirstActivity时,首先会清空FirstActivity所在的任务栈,而后再建立新的FirstActivity实例并入栈,这和taskAffinity属性相同是一致的效果,只不过这里第一次为FirstActivity建立了新的任务栈

综上所述,当经过FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK标志位组合启动目标Activity时,首先会清空目标Activity所在的任务栈(若目标Activity是第一次启动,那么会清空目标Activity所指望的任务栈),而后建立新的目标Activity实例并入栈。

FLAG_ACTIVITY_SINGLE_TOP

该标志单独使用就能够达到SingleTop启动模式的效果,该类效果能够参考前篇文章,这里再也不赘述。

Activity启动相关的属性

这里简单介绍一些AndroidManifest配置文件中与启动模式相关的属性。其实前一篇文章已经介绍了两个比较经常使用的属性:android:taskAffinityandroid:allowTaskReparenting,下面再补充一些不经常使用的属性。

android:clearTaskOnLaunch

字面意思是:是否在启动时清除任务栈,该属性默认为false,表示是否在APP启动时,清除任务栈中除根Activity以外的其余Activity实例。该属性只对任务栈内的根Activity起做用,任务栈内其余的Activity都会被忽略。

好比:咱们有一个App,依次启动了ActivityA、ActivityB和ActivityC,其中ActivityA和ActivityB都设置clearTaskOnLaunch属性为true。那么首先点击“Home”建回到Launcher界面,而后再启动该App,咱们看到是ActivityA界面,而ActivityB和ActivityC都被销毁了。 除非栈底的ActivityA已经被销毁,那么上面设置clearTaskOnLaunch属性为true的activity(B)才会生效。

android:finishOnTaskLaunch

该属性默认值为false,表示当离开当前Activity所在的任务栈时,当即销毁当前Activity,而其余Activity不受影响。

android:alwaysRetainTaskState

该属性默认值为false,表示App的任务栈是否保持原来的状态。该属性只对task的根Activity起做用,其余的Activity都会被忽略。 默认状况下,若一个App在后台停留的时间太长,那么再启动该App时,系统会清除任务栈中除了根Activity以外的其余Activity,可是若是根Activity设置了该属性,那么再次启动应用时,就不会清除Task中的Activity,而是保持原样,所以仍然能够看到上一次操做的界面。


OK,Activity启动模式相关的内容就介绍这些吧,但愿对本身对感兴趣的同窗都有所帮助^_^。

相关文章
相关标签/搜索