Activity启动模式解析


Activity有四种启动模式:standard,singleTop,singleTask,singleInstance。

关于这四种启动模式的概念很容易找到,这里我们先不介绍概念,而是通过实际操作,总结出不同模式的实际效果。

Task简介

当然,要了解启动模式,我们就不得不提到Task,直译过来是“任务”,而实际上它的本质是一个栈,一个专门存储activity的栈。通常情况下,当我们启动一个新activity时,执行的是入栈操作,会把activity压入栈。当点击返回时,执行的是出栈操作,让当前activity出栈,这样就显示出了上一个activity。


启动模式设置方式

此外,要了解启动模式,还需要知道如何设置,启动模式的设置有两种方式,一种是在AndroidManifest.xml中进行配置,另一种是在启动activity时设置intent的flag。

首先看AndroidManifest.xml中的设置:

很简单,就是这四种模式,当我们不设置的时候,默认是standard模式。

另一种方式则相对复杂,我们可以通过Intent的setFlags()或addFlags()方法来设置Flag,而Intent关于启动模式的Flag有许多:

我们可以同时设置一种或多种。幸运的是每个都有详细的注释和例子,当我们理解了启动模式的原理以及熟悉了其中部分的应用方式,其他的也可以根据注释很容易的进行应用。

通过Intent设置flag的方式的优先级要高于在AndroidManifest.xml中的配置。

 

Standard

首先我们来看一下最常用的standard模式:

我写了两个简单的应用,LaunchMode1一共有四个activity,他们可以互相跳转。LaunchMode2有一个activity,可以和LaunchMode1互相跳转。通过adb shell dumpsys activityactivities命令我们可以看到task栈的情况


执行:0——1——2——3:

执行:0——0——0:

执行:0——LaunchMode2——0:

可以看到,无论是启动同应用的activity,启动自身,还是跨应用的activity,只要是新启动activity,都会在当前task内重新创建一个实例。这就是standard启动模式。

 

SingleTop

接下来我们看一下singleTop模式:

这里Intent的flag中有一个FLAG_ACTIVITY_SINGLE_TOP,和在AndroidManifest.xml中设置android:launchMode="singleTop"是一样的。我们这里采用的是AndroidManifest.xml设置方式。

执行:0——1——2——3:

和standard模式一模一样的结果,差点让我以为是我设置错了,我们看看下面会不会有区别。

执行:0——0——0:

这里就已经不一样了。

执行:0——LaunchMode2——0:

这个好像还是没什么区别。我们再试一组

执行:0——1——2——2:

这里也和standard不同,点了四次却只有三个记录。结合singleTop的名字我们就可以看出来了。如果打开的avtivity刚好在栈的顶部,那么就不会创建新的实例,而是打开原来的(那么怎么证明我点过了,而不是没有任何操作呢?其实这时会执行onNewIntent()方法,可以在这里执行我们想要的操作)。如果要打开的activity不再栈顶,则和standard模式一样。

 

SingleTask

接下来是singleTask模式:

这个模式也有两种设置方式:android:launchMode="singleTask"以及FLAG_ACTIVITY_NEW_TASK
我们还是选择在AndroidManifest.xm中设置。

说到这种模式,我们不得不提到activity的一个属性taskAffinity,从字面意思看,就是对任务栈的亲和力。而事实上也差不多,它决定了activity运行在哪个task,默认是app的包名。

现在我们就把每个activity启动模式设置为singleTask,并把activity3的taskAffinity属性设置为“com.example.mjn.launchmodetest”

 

执行:0——1——2——3:

可以看到012在一个task中,而3启动了新的task,名字刚好是我们之前设置过的。

执行:0——1——2——1:

这里2被清除了

执行:0——1——LaunchMode2——0:

这里1被清除了

执行:0——3——LaunchMode2:

不同应用由于默认包名不同,启动在不同的task。

通过这几个现象我们可以看到,首先activity会启动到taskAffinity属性设定的task中,默认是包名。而当activity在所需task中已经存在时,则会把之前的实例放到栈顶,把在该activity上面的实例全部推出栈。

 

SingleInstace

最后一个singleInstance模式

顾名思义,也就是单例模式,我们依然先看效果。

这里有一点要注意的是singleInstance模式只能通过manifest设置,不能在intent中设置,这个当我们明白他的原理后也很好理解。

 

执行:0——1——2——3:

可以看到每个activity都在不同的task,而且taskAffinity属性依然有效。

执行:0——1——2——1:

每个acitivity都在自己独立的task,互不影响。由此就可以看出singleInstance模式就是格的例模式,每个acitivty在一个task中且只有一个例,每个task只有一个activity。这里我们就能理解为什么不能再intent中设置该模式了,因为singleInstance要求每个activity都在单独的task,若不是一开始就设置为该模式,很可能出现task有多个activity,activity有多个实例等情况,造成问题。

 

总结

以上,就是四种启动模式的介绍,我们来总结一下:

Standard:

       默认模式,启动每个acitivity时都会在当前task创建新的实例。

SingleTop:

       当要启动的activity在目标task顶部时,不会创建新实例,而是重用该实例并调用onNewIntent()方法。否则创建新实例。

SingleTask:

    当要启动的activity不存在时,会在在目标task(目标task可又taskAffinity属性设定)中创建新实例,若目标task中已存在该activity,则会重用该实例,并调用onNewIntent()方法,并把task栈中在它上面的activity移除。该模式下的Activity只会有一个实例。

SingleInstance:

    当要启动的acitivity不存在时,会在新task中创建一个实例,如果存在,则重用之前的实例。每个acitivity都在一个独立的task中,只有一个实例,每个task只有一个实例。

 

对返回键的影响

此外,我们在开始时就说过task还和返回有关,我们点击返回是显示的activity就是由task决定的。我们上面每个关于栈内容的截图都显示了返回的顺序:

例如singleTask时执行:0——1——2——1:


就表示返回时是1——0的顺序。而和我们打开的顺序并不相同,所以不同的启动模式会对我们返回操作产生影响。

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值