Activity LaunchMode,TaskAffinity及Flag相关资料详细整理.
一.Activity的LaunchMode
(1) standard:标准模式,也是系统默认模式,每次启动一个Activity都会重建一个新的实例,不管这个Activity是否已经存在.这种模式下,一个任务栈可以有多个实例,每个实例也可以属于不同的任务栈,谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中.但是如果是非Activity的context启动它时,会报错,需要为待启动的Activity添加FLAG_ACTIVITY_NEW_TASK标记.这时,待启动的Activity实际上是以singleTask模式启动的.
(2)singleTop:栈顶复用模式.这种模式下,如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时它的onNewIntent方法会被回调,通过此方法的参数我们可以取出当前请求的信息.这个Activity的onCreate,onStart不会被系统调用.如果新Activity的实例已存在但是不是位于栈顶,那么这个新Activity仍会被重新创建.
(3)singleTask:栈内复用模式.在一个任务栈中,只要目标Activity的实例存在,那么多次启动此Activity都不会重新创建实例,系统会调用存在的那个Activity实例的onNewIntent方法.同时singleTask模式默认具有clearTop的效果,如果当前任务栈的情况为ABCD(表示Activity实例),用这个模式启动B,那么会导致栈内所有在B上面的Activity全部出栈,于是此任务栈中的情况变为AB.
(4)singleInstance:单实例模式.具有此模式的Activity只能单独的位于一个任务栈中,如果 Activity A是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A独自在这个新的任务栈中,由于栈内复用的特性,后续的请求都不会创建新的实例,除非这个独特的栈被系统销毁了.
有两种方法可以指定Activity的启动模式,第一种是通过AndroidMenifest指定,另一种是通过Intent中设置标志来指定.区别是第二种的优先级高于第一种,其次是这两种方式的限定范围不同,比如第一种无法为Activity指定FLAG_ACTIVITY_CLEAR_TOP标志,二第二种方法无法为Activity指定singleInstance模式.
二.Activity的TaskAffinity
TaskAffinity可以翻译为任务相关性,这个参数标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名,我们可以为每个Activity单独指定TaskAffinity属性,这个属性值不能和包名相同,否则相当于没有指定.TaskAffinity属性主要和singleTask启动模式或者allowTaskReparenting属性配对使用,其他情况下没有意义.
1.当TaskAffinity和singleTask启动模式配对使用时,它是具有该模式的Activity的目前任务栈的名字,待启动的Activity会运行在名字和TaskAffinity相同的任务栈中.
2.当TaskAffinity和allowTaskReparenting结合使用时.举个例子,当应用A启动应用B的某个Activity后,如果这个 Activity的allowTaskReparenting属性为true的话,那么当应用B被启动后,此Activity会直接从应用A的任务栈转移到应用B的任务栈中.比如应用A启动了应用B的一个Activity C,然后按home键回到桌面,然后在单击应用B的桌面图标,这时启动的不是应用B的主Activity,而是Activity C,或者说C从应用A的任务栈转移到了应用B的任务栈.可以这么理解由于应用A启动了Activity C,这时C只能运行在A的任务栈中,但是C属于应用B,并且C的TaskAffinity值为应用B的包名,所以当B启动后,B会创建自己的任务栈,这时系统发现C所需要的任务栈被创建了,所以把C从A的任务栈转移到了B的任务栈.
现在看一个例子:假设在一个应用中有三个Activity,分别是MainActivity A, SecondActivity B, 和ThirdActivity C .我们将B和C设置成singleTask并指定它们的TaskAffinity属性为"com.test.mytask",这个属性值为字符串,并且中间必须含有包名分隔符"." ,然后打开应用,进入A,在A中启动B,在B中启动C,在C中启动A,最后在A中启动B,现在按2次back键,会看到哪个Activity呢?答案是回到了桌面,下面分析一下:
A没有指定任何模式和属性,所以它是standard模式,A的TaskAffinity属性值是默认值即应用的包名,我们设置了B和C为singleTask模式,并且具有相同的TaskAffinity值"com.test.mytask".当A启动B时,会为B创建一个新的名为"com.test.mytask"的栈,B启动C时,由于C所需要的任务栈已经创建了,所以C的实例会直接进入B所在的那个栈,接着C在启动A,A是standard模式,所以A会创建一个新的实例并添加到启动它的那个Activity所在的栈中,即名为"com.test.mytask"的这个栈.这时存在两个A的实例,一个在名为应用包名的任务栈中,另一个在名为"com.test.mytask"的任务栈中,现在名字为包名的任务栈里面只有一个A,我们指定的"com.test.mytask"这个栈,里面的Activity为BCA,接下来A再启动B,由于B是singleTask模式,B需要回到栈顶,那么它上面的Activity都会出栈,这时这个栈中只存在一个Activity B,然后按back键,B出栈,B所在的任务栈不存在,这时回到后台任务栈,并把A显示出来,接着再按back,回到桌面.
三.Activity的Flags