谈谈Activity生命周期和启动模式(二)

上篇讲述了Activity的生命周期,这篇我们来聊聊启动模式(LaunchMode),下面开始正文


Activity任务栈(Task)

在说启动模式之前,我们先了解下Activity的任务栈,什么是任务栈?举个例子,今天我们需要做一个搜索功能,那么这个搜索功能就是一个任务,开发这个功能需要用到Activity,那么,当我们启动这个Activity时,系统会给我们创建一个容器,去存储我们所需的Activity,这个容器就是Activity的任务栈,主要是存储我们的Activity,在默认情况下,每个应用都有一个Task,每当创建一个新Activity,就会加载到Task之中,每个Activity都可以跨进程进行通信,最简单的例子就是,点击打电话按钮,唤起系统的打电话界面,Task遵循的是先进后出顺序,也就是说,最新创建出来的Activity会处于栈顶


后台任务栈(Back Stack)

什么是后台任务栈?当ActivityA打开了ActivityB,打开之后,ActivityA就会被存放到Back Stack之中,当点击back键返回到ActivityA的时候,系统先把ActivityB销毁,然后从Back Stack中把ActivityA拿出,Back Stack遵循的顺序是后进先出,也可以说是先进后出,例如上面的例子,用户在启动了打电话界面后,我们应用的Activity就会存放到Back Stack之中,当用户点击了back键返回我们应用时,系统就会从Back Stack中将Activity拿出来显示给用户,如果用户继续点击back键,则一层一层的将Activity拿出来显示,如果Back Stack中没有了Activity,那应用就退出了,这里要注意一点是,如果ActivityA打开ActivityB之后就finish了,那么ActivityA是不会被添加到Back Stack中,如果有多个Task的话,用户点击back回退时,系统会先从当前Activity所处在的Task中回退,直到没有了Activity,再去寻找下一个Task回退,以此循环,至于怎么知道Task的排序,其实创建Task的时候,系统就会帮我们记录好了

这里就不进行深入的探讨了,有兴趣的自己去研究下


LaunchMode

Activity的启动模式有4种:standard,singleTop,singleTask,singleInstance,现在就来说说他们的差别

1,standard:Activity默认的启动模式,在这种启动模式下,每一个Activity创建之后,都会加载到Task之中,也是大多数场景用到的,但这有个弊端就是Task中的Activity越来越多,即使是同名的Activity,也会被创建,举个例子,在ActivityA中添加个button,点击之后启动自己,这时,系统会继续帮我们创建ActivityA,任务栈中就会继续添加ActivityA

2,singleTop:这种模式就是说取出栈顶的Activity,假设有A,B,C,D四个Activity,ActivityD处于栈顶,这时候ActivityD启动它自己,系统就不会创建一个ActivityD,而是回调ActivityD的onNewIntent方法,假如ActivityD不处于栈顶,系统则会创建出来,所以,总结就是,当Activity处于栈顶并且启动自己的时候,才不会被创建,否则都会被创建出来

举个例子:假如有个SearchActivity,有个输入框,输入商品名字后搜素需要跳转到另一个SearchResultActivty,而SearchResultActivty中也有搜索功能,假如是standard模式,我连续搜索10条,那么系统就会创建10个一模一样的Activity,用户得需要点击10次back才可以返回到最初的Activity,这显然是不合理的,而如果是singleTop模式,这样我搜索出来结果之后,启动自己,然后回调onNewIntent方法,获取到数据之后刷新,是不是就合理多了呢?

3,singleTask:指的是当前Activity是唯一的,不允许有多个存在,如果已经存在了,再次启动它的时候,它就会调用onNewIntent方法,如果不存在,系统就会帮我们创建出来,这个模式比较复杂,下面单独拿出来说

4,singleInstance:跟singleTask有点类似,但差别就是,任务栈中只允许有目标Activity,也就是说,如果是这种模式启动的Activity,系统会单独分配一个Task给Activity,而Task中只有这个Activity,如果多个Activity是以这种模式启动的,那就会存在多个Task


singleTask

我们先来看一个例子,首先创建两个Activity,MainActivity和SecondActivity,SecondActivity指定启动模式是singleTask,然后MainActivity启动SecondActivity,SecondActivity中可以启动MainActivity和它自己,我们来看看变化


1,首先MainActivity创建的时候,打印下TaskId,然后我们启动SecondActivity


2,SecondActivity第一次创建时,打印出的Task的Id,我们发现两个Id是一样的,因为他们处在同一个任务栈中,然后SecondActivity启动MainActivity

3,Id还是一样,但注意了,因为MainActivity是默认模式启动的,所以这里的MainActivity被创建了两次实例,然后我们继续启动SecondActivity

4,神奇的地方来了,之前说了SecondActivity如果存在,就不会重新创建,但是,为什么MainActivity会被销毁了呢?那是因为,指定了singleTask模式的Activity被启动的时候,它会先检查是不是处于栈顶,如果不是,它会将在它之上的Activity全部销毁掉,在第2步的时候我们启动了MainActivity,这时候MainActvity处于SecondActivity之上,再去启动SecondActivity时候,它就会将MainActivity销毁

5,然后SecondActivity启动自己的时候,就跟之前一样了,实例存在了就调用onNewIntent方法

taskAffinity

这个属性是指Activity希望进入的是哪个Task,每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有指明该 Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果 Application也没有指明,那么该taskAffinity的值就等于包名。而Task也有自己的affinity属性,它的值等于它的根 Activity的taskAffinity的值

singleTask建议和taskAffinity一起使用,这样才会发挥它最好的效果,那么,他们是怎么工作的呢?

1、如果存在,那么检查是否实例化,如果已经实例化,那么销毁在该Activity以上的Activity并调用onNewIntent。如果没有实例化,那么该Activity实例化并入栈。
2、如果不存在,那么就重新创建Task,并入栈。

这里不做深入的描述了,有兴趣的可以去看看这个属性,现在来说说该注意的地方:

1,具有相同的affinity的activity(即设置了相同taskAffinity属性的activity)属于同一个任务。

2,默认情况下,一个应用中的所有activity具有相同的taskAffinity,即应用程序的包名。我们可以通过设置不同的taskAffinity属性给应用中的activity分组,也可以把不同的应用中的activity的taskAffinity设置成相同的值。

3, 为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task。

4,如果不设置这个属性,则Activity都会同处在同个Task中,如果设置了,则会为Activity开启一个新的Task,然后将同个taskAffinity属性的Activity列入

为什么说最好singleTask建议和taskAffinity一起使用呢?当我们指定了taskAffinity之后,用户点击back回退的时候,会遵循Back Stack的回退原则,因为指定taskAffinity的Activity是单独在一个Task里面,所以回退的时候不会回退到我们之前的Activity,就不会影响我们之前Activity的逻辑了

最后来看看指定了taskAffinity和没指定taskAffinity的Task的差别,方法很简单,在AndroidMainfest.xml里指定就可以了

没指定taskAffinity
指定了taskAffinity

不难看出,默认情况下是同处在一个Task中,而指定的,则会单独分配出一个Task

好了,这篇文章到这就结束了,如果什么建议欢迎提出来,反正我也不会改,哼~

你可能感兴趣的:(谈谈Activity生命周期和启动模式(二))