一道题目带你充分理解Android Activity四大启动模式

前言

Activity作为android的四大组件之一,它的重要性不言而喻!而本期的主题也是activity,和大家分享一下activity的四大启动模式!至于activity的生命周期,如果作为一个android开发你还不对activity生命周期烂熟于胸的话。请面壁思过转行ios。。。。。。。

1)抛砖引玉!

先介绍一下四大启动模式的基本功能:

standard加载模式:

每次通过这种模式启动Activity时,Android总会为启动的Activity创建一个新的实例,并将该Activity添加到当前Task栈中,这种模式不会创建新的Task,只是将新Activity添加到原有的Task 中

singleTop模式

如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。

singleTask模式

被启动的Activity在同一个Task内只有一个Activity实例,具体分为如下三种情况:

<1>.如果启动的目标Activity不存在Task栈中,系统将会创建一个目标Activity实例,并将它加入到Task栈顶

<2>.如果启动的目标Activity已存在Task栈顶,此时模式和singleTop模式相同

<3>.若果启动的目标Activity已存在但没有位于Task栈顶,系统将会把该目标Activity上面的所有Activity移除Task栈,使该Activity置于Task栈顶

singleInstance模式

这种加载模式下,无论从哪个Task中启动目标Activity,只会创建一个目标Activity实例,并会使用一个全新的Task栈来装载该Activity实例。具体可分为两种情况:

<1>.如果创建的目标Activity不存在,系统先会创建一个全新的Task,接着创建一个Activity实例,然后将该目标Activity加入到新的Task栈顶

<2>.如果创建的目标Activity已经存在,无论在哪个Task栈中,系统将会把Activity所在的栈置于前台。

一个应用有4个Activity ,ABCD,他们的启动模式分别为standard,singleTop,singleTask,singleInstance.

现在A>B>C>D>A>B>C>D 。A启动B,B启动C,C启动D,D启动A,A启动B,B启动C,C启动D。

现在这个应用ABCDAcvity实例 各几个????有几个Acvity栈???

对于这个问题!有把握答上来???能答出几个答案????

什么??这个问题不止一个答案?你忽悠我??

答案不就是ABCD各一个实例,2个Activity栈吗???

2)实践是检验真理的唯一标准!

很多时候,我们可以选择去敲代码去验证一些问题。这个问题同样可以!

新建一个工程---创建四个actvity。分别给他们设置启动模式.

然后顺着操作

A启动B,B启动C,C启动D,D启动A,A启动B,B启动C,C启动D。

代码非常简单,就不贴出具体的代码.

然后----

然后----

我擦ABCDAcvity实例 各几个????有几个Acvity栈???

不要急!

adb shell

dumpsys activity activities,

下面是一些剪贴的信息:

  1. 一个栈只有D实例 **Activities=[ActivityRecord{bc402f7 u0
    com.example.testactivity/.DActivity t7}]**

  2. 另一个栈有ABC实例 **Activities=[ActivityRecord{a0dbe14 u0
    com.example.testactivity/.AActivity t6}, ActivityRecord{928da88 u0
    com.example.testactivity/.BActivity t6}, ActivityRecord{2f8fa2a u0
    com.example.testactivity/.CActivity t6}]**

两句命令行搞定。

不过美中不足的是。没有问题??大家再仔细想想。。。

这里给大家一个提示taskAffinity!

3)走的最远的肯定是想的最多的!

我由于一些工作的原因。很早就接触到了taskAffinity。下面是taskAffinity的一些介绍。每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明该 Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果 Application也没有指明,那么该taskAffinity的值就等于包名。而Task也有自己的affinity属性,它的值等于它的根 Activity的taskAffinity的值。

看到这里相信大家都有所领悟。对于四大启动模式中最特殊的singleTask.他是有选择栈的权利的。

所有当CActivity的taskAffinity设置成区别于AActivity的taskAffinity。就完全会发生另外一种情况!

现在改动一下androidmanifest.文件中对cActivity的启动模式。操作完毕,我们来看一下最后结果!
下面是一些剪贴的信息:

1.栈1只有D实例
Activities=[ActivityRecord{5abae31 u0 com.example.testactivity/.DActivity t10}]
2.栈2只有C实例
Activities=[ActivityRecord{c2fabaf u0 com.example.testactivity/.CActivity t9}]
2.栈3 有ABAB实例
Activities=[ActivityRecord{8735656 u0 com.example.testactivity/.AActivity t8}, ActivityRecord{39e4078 u0 com.example.testactivity/.BActivity t8}, ActivityRecord{54647d9 u0 com.example.testactivity/.AActivity t8}, ActivityRecord{4949877 u0 com.example.testactivity/.BActivity t8}]

4)总结。

1)当CActivity的taskAffinity 和大家一样时启动流程是这样的:
A启动B 没有任何波澜,他们都是在一个堆栈,取名栈1,启动C,c寻找taskAffinity一样的栈,发现栈1,而栈1中没有C实例,所有创建C实例。启动D时。
D为singleInstance,所有会另开一个栈,存放D。一轮启动过后!目前栈为2个,
栈1里面的实例是ABC
栈2里面的实例是D
D启动A=》A会在栈1中创建
栈1里面的实例是ABCA
栈2里面的实例是D
A启动b=》B会在栈1中创建
栈1里面的实例是ABCAB
栈2里面的实例是D
B启动C=》由于但是由于栈1有c,所有singleTask的特性会将c上的实例通通清除
栈1里面的实例是ABC
栈2里面的实例是D
C启动D=》D为singleInstance,而现在D又有实例,所有不会创建新的,复用原本的D实例
栈1里面的实例是ABC
栈2里面的实例是D
最终结果是:ABCD实例各一个,栈2个

2)当CActivity的taskAffinity 和大家不一样时启动流程是这样的:
A启动B 没有任何波澜,他们都是在一个栈,取名栈1,启动c时。由于C的taskAffinity和A不一样,也就是栈1不一样,所有会单独创建一个栈2,存放C。C启动D,D为singleInstance,所有会另开一个栈3,存放d。一轮启动过后!目前栈为3个,
栈1里面的实例是AB
栈2里面的实例是C
栈3里面的实例是D
D启动A=》A会在栈1中创建
栈1里面的实例是ABA
栈2里面的实例是C
栈3里面的实例是D
A启动b=》B会在栈1中创建
栈1里面的实例是ABAB
栈2里面的实例是C
栈3里面的实例是D
B启动C=》C会去找taskAffinity相同的栈,也就是栈2,栈2的c在最上面所有复用C实例,
栈1里面的实例是ABAB
栈2里面的实例是C
栈3里面的实例是D
C启动D=》D为singleInstance,而现在D又有实例,所有不会创建新的,复用原本的D实例
栈1里面的实例是ABAB
栈2里面的实例是C
栈3里面的实例是D
最终结果是:AB实例各2个,CD实例各1个,栈3个

以下是具体代码
https://github.com/wy100200/TestActivity
希望这些能给想要理解四大启动模式的你一点帮助!

码农的路上,纵情向前!

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页