前言
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,
下面是一些剪贴的信息:
一个栈只有D实例 **Activities=[ActivityRecord{bc402f7 u0
com.example.testactivity/.DActivity t7}]**另一个栈有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
希望这些能给想要理解四大启动模式的你一点帮助!
码农的路上,纵情向前!