Activity启动模式学习

最近学习了Activity的启动模式,这里记录下,以便以后回顾

Activity有四种启动模式,分别为:
* standard
* singleTop
* singleTask
* singleInstance

standard

默认情况下,系统会以standard模式来启动activity,这种模式下系统会创建一个新的activity实例。
这里写图片描述

singleTop

指定Activity的启动模式为singleTop时,当被启动的Activity B已经存在一个实例,并且位于任务栈的栈顶,这时候系统就不会生成一个新的Activity B,而是回调Activity B的onNewIntent函数

如下图示
这里写图片描述

可以看到,第二次启动Activity B,系统并没有创建新的Activity B的实例,而是回调了已经存在于任务栈栈顶的Activity B的onNewIntent函数。

这种模式适用于那些布局几乎一样,而内容存在变化的Activity,比如新闻类APP的新闻展示页面就可以使用singleTop模式,这样当用户正处于具体新闻的展示页面时,当用户点击任务栏里面的推送新闻时,可以不用创建新的Activity而直接用已经存在的Activity,节省资源的开销。

singleTask

singleTask可以理解为single in desired task,即在所指定的task里面只能存在一个实例。每一个Activity都可以在manifest里面通过TaskAffinity指定自己所在的task的名称,如果不指定的话,系统将使用默认的任务栈。
启动一个singleTask的Activity B,系统会做以下几步操作:
1.寻找Activity所在的task(假定名字为A),如果A不存在,则创建task A
2.在task A中寻找Activity B,如果B已存在,那么将B之上的所有Activity出栈,然后回调Activity B的onNewIntent方法,如果B不存在,那么创建B,并将之压入栈A中。

以下是我自己尝试的几个singleTask例子。

以下例子均省略A的启动步骤

例子1

有3个Activity:
* A standard
* B singleTask,未指定TaskAffinity
* C singleTask,未指定TaskAffinity

启动顺序A->B->C
singleTask模式的Activity B启动时系统会去寻找其TaskAffinity指定的任务栈,而这里我并没有设置TaskAffinity属性,故而系统会使用默认的值(程序包名)去寻找任务栈,找到的任务栈(task)就是默认的任务栈,即A所在的任务栈。然后在任务栈中去寻找Activity B,由于当前并没有B存在,故而系统会创建一个新的实例压入栈中,然后通过B启动C过程是一样的。
整个过程中并没有创建新的任务栈(task)

这里写图片描述

例子2

有3个Activity:
* A standard
* B singleTask,指定TaskAffinity为feitengbing
* C singleTask,未指定TaskAffinity

启动顺序A->B->C

这里写图片描述

图中红色的是默认的任务栈,当启动Activity B时,由于B指定了TaskAffinity为feitengbing,故而系统会去创建名为feitengbing的task(图中的蓝色部分),然后在这个新创建的task中创建Activity B的实例。当启动C的时候又不一样了,由于C没有有指定TaskAffinity,故而系统会按照默认值(程序的包名)来寻找任务栈,找到的task是默认的任务栈,及我们图中的红颜色任务栈,系统会把这个task挪到前台(foreground),然后在其中去寻找C,由于C不存在,故而创建一个新的C的实例。

当按返回键回退时你就会发现,原来的启动顺序是 A -> B -> C,但是回退顺序却是C -> A -> B.正如上图所描述的那样

例子3

有3个Activity:
* A standard
* B singleTask,指定TaskAffinity为feitengbing
* C standard

这里写图片描述

这个例子区别于例子2在于C使用standard启动,故而会使用直接在当前task中创建新实例,这次在往回退时其顺序和启动顺序刚好相反 C -> B -> A

例子4

在网上看到有人说如果launchMode指定为singleTask或者singleInstance时,若不指定TaskAffinity属性,那么launchMode就会被系统忽略,那么就找个例子试一下

这里写图片描述

这个例子有 A.B.C.D 4个Activity,其中B的启动模式为singleTask,并且没有指定TaskAffinity属性,这个例子运行的结果,如上图所示,在Activity D中启动Activity B,系统并没有去创建新的Activity B,而是遵循singleTask模式,去相应的任务栈中寻找Activity B,由于当前任务栈是存在Activity B的,故而清空了Activity B上面的其他Activity,然后回调Activity B的onNewIntent函数,这里面的操作都是按照singleTask模式来执行的,结合上面的例2可以得出,当Activity指定启动模式为singleTask,但没有指定TaskAffinity属性时,系统并没有忽略该启动模式。

singleInstance

看名字就知道是单例模型,这个模式下启动的Activity系统会为之单独创建一个task(即使没有指定TaskAffinity属性也会创建),这个新创建的task中有且仅有该Activity,如果在这个Activity里面去启动其他的Activity,其效果就相当于在用于启动Activity的intent里面加上FLAG_ACTIVITY_NEW_TASK标志位。

这里写图片描述

上图中启动Activity C时,无论C是什么启动模式(图片里面C是standard模式),都不会在Activity B所在的task里面创建新Activity,而Activity C到底会出现在哪个task里面,这个就跟其具体的启动模式有关了。

以上就是Activity在manifest中静态注册的四种启动模式。

除了在manifest中静态注册之外,我们还可以在启动Activity的intent当中指定标志位来达到上述目的,可以设置的标志位有以下这些:

FLAG_ACTIVITY_CLEAR_TASK 清空activity指定的任务栈(taskAffinity指定,或者默认),再启动Activity
FLAG_ACTIVITY_CLEAR_TOP 相当于singleTask模式下的Activity存在时的情况
FLAG_ACTIVITY_FORWARD_RESULT
FLAG_ACTIVITY_NEW_DOCUMENT
FLAG_ACTIVITY_NEW_TASK,当我们在非Activity上下文(Service,Application等)里启动Activity时,无论Activity是什么启动模式,都必须添加这个标志位
FLAG_ACTIVITY_PREVIOUS_IS_TOP
FLAG_ACTIVITY_REORDER_TO_FRONT
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_SINGLE_TOP 相当于singleTop模式
FLAG_ACTIVITY_TASK_ON_HOME

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值