简单说说安卓的四种启动模式

  在Android应用程序中,Activity可以以四种方式来启动,分别是standard、singleTop、singleTask和singleInstance,怎么区分这四种启动模式呢?
  在这之前,先交代一下“任务(task)”这个概念。在安卓中,每个应用都默认是一个任务,这种实现基于所有的activity都以standard方式启动。每个任务都是一个栈型结构,不知道栈的可以想象一下一个桶,这个任务的每个activity都像一块砖头,先调用的砖头先放入任务桶里,一般而言我们只能拿到最顶端的砖头,想要取得非顶端的砖头有两种方式,一种是把桶中间凿一个洞,一种是把砖头一个个取出来。对应到安卓中,这两种方式就是intent跳转和不停地按下手机的返回键。
  类似操作系统的多线程,安卓也有多任务的概念,不仅两个应用可以实现多任务,一个应用内部也可以实现多任务。不同任务之间可以实现跳转,每个任务都是一个单独的栈。
  对于两个任务之间的跳转,假设分别为任务1和任务2,我们要从任务1中的Activity跳转到任务2的某个activity(假设命名为test),可以分为两种情况:
  (1)任务2中不存在test。此时会在任务2中新建一个test并实现跳转。
  (2)任务2中已经存在test。此时会直接跳转到任务2中,但是注意,不会直接跳转到任务2中的test,而是跳转到任务2栈顶的那个activity,且不会新建一个实例,即使那个activity是standard的。我们可以理解为任务之间没有访问非栈顶activity的权限。但是有一个例外,就是test启动模式为singleTask的时候,系统会直接清除栈中位于test上的所有activity,从而访问到test。
  明了了任务的概念,就可以开始说说安卓的四种启动模式了。
  
 1、standard
  standard是安卓activity默认的启动模式,只要是跳转到设置为standard的界面,会默认和前一个界面属于同一个任务,并像是垒砖头一样往栈里塞,不停的塞,不管你是不是已经有了这个activity。所以设置为standard的activity每次调用都是一个新的界面,要重新oncreate一遍。
  举个简单的例子:
  A(standard,任务1)
  B(standard)
  执行A->B->B。
  A跳转到B,因为B是standard启动模式,所以会新建一个B,叠在A的上面,并且B也属于任务1。B跳转到B,会再新建一个B,叠在原来的B上,同样属于任务1。最终的示意图如下(上面为栈顶):
  ——————–栈顶
  【B】
  【B】
  【A】
  ——————–栈底
  任务一栈
 
 2、singleTop
 singleTop和standard很像,唯一的区别在于,当前任务栈顶的这个activity在这个栈中是“single”唯一的。如果当前我在看微博,当前我在看的这个热门界面被设置为singleTop,那么当我点击刷新,按理应该重新打开这个界面,可是这个界面由于是最后执行(当前我正在看)而被置于栈顶,栈顶activity唯一导致我跳转到同一个界面的时候会回到原来刷新前的“被用过”的activity,由此导致刷新失效。
 还是上面那个例子,修改B的启动模式为singleTop:
 A(standard,任务1)
 B(singleTop)
 A跳转到B,B是singleTop启动模式,现在的栈顶activity为A不是B,所以会新建一个B,叠在A的上面,并且B也属于任务1。B继续跳转到B,因为此时栈顶activity变为B,所以不会再新建一个B,用户会发现什么变化都没发生。最终的示意图如下(上面为栈顶):
  ——————–栈顶
  【B】
  【A】
  ——————–栈底
  任务一栈

 3、singleTask
 singleTask顾名思义,在所有任务中只有唯一一个实例,和singleInstance的区别在于singleInstance不仅在所有任务中只有唯一一个实例,且所处的任务栈中只能有它这个activity。
 启动模式设置为singleTask的activity在启动的时候,会先在系统中查找属性值affinity等于它的属性值taskAffinity的任务是否存在。如果存在这样的任务,它就会在这个任务中启动,且会将该任务栈中处于该activity上的所有activity全部删除。如果不存在,就会在新任务中启动。
 所以如果有两个activity的属性值taskAffinity相同,那么它们就会在同一个任务中,且较晚创建的activity不会处于栈底。下面是个例子:
 A(singleTask,taskAffinity=“testA”,任务1)
 B1(singleTask,taskAffinity=“testB”)
 B2(singleTask,taskAffinity=“testB”)
 执行A->B1->A->B2->A->B1。
 A跳转到B1,B1是singleTask启动模式,taskAffinity=“testB”,系统检测所有任务的taskAffinity,发现没有taskAffinity为testB的任务,所以创建了一个任务2,在任务2中创建了B2,并跳转。
  ——————–栈顶     ——————–栈顶
  【A】       ——> 【B1】
  ——————–栈底     ——————–栈底
  任务一栈          任务2栈
 B1跳转到A,系统检测所有任务的taskAffinity,发现任务1的taskAffinity为testA,并在任务1栈中发现了A的实例,所以直接跳转。
  ——————–栈顶     ——————–栈顶
  【A】        <—— 【B1】
  ——————–栈底     ——————–栈底
  任务一栈          任务2栈
 A跳转到B2,B2是singleTask启动模式,taskAffinity=“testB”,系统发现任务2的taskAffinity为testB,并且没有在任务2中发现B2的实例,所以在任务2中创建了B2,置于栈顶并跳转。
  ——————–栈顶     ——————–栈顶
            ——>  【B2】
  【A】             【B1】
  ——————–栈底     ——————–栈底
  任务一栈          任务2栈
 B2跳转到A和B1跳转到A是一样的过程,就不赘述了。
 最后要从A跳转到B1,因为B1已经在任务2中存在,所以不会重新创建一个实例,而是直接跳转到B1,但是在这之前,系统会先把位于B1上的所有activity全部删除,因此B2被删除,如果用户不断按返回键,会发现无法返回到B2的页面。
 最终的示意图如下:
  ——————–栈顶     ——————–栈顶
  【A】           【B1】
  ——————–栈底     ——————–栈底
  任务一栈          任务2栈

 4、singleInstance
 singleInstance和singleTask的区别在于singleInstance不仅在所有任务中只有唯一一个实例,且所处的任务栈中只能有它这个activity。也就是说,启动模式为singleInstance的activity独立组成一个任务。
 
 下面是一个促使我去了解这四种启动模式的例子:
 A(singleInstance,任务1)
 B1(standard)
 B2(standard)
 执行A->B1->A->B2->A->B1。
 也许有人会说最后的结果就是跳转到B1,且B2依然在栈顶,但是事实上只对了一半,因为最后B2依然在栈顶,但是却无法跳转到B1。究竟这是怎么样的一个过程呢?
 A跳转到B1,B1是standard启动模式,照理说应该创建在A所处的任务1中,但是因为A是singleInstance,无法与其他activity共享同一个任务,因此系统为B1单独开启了一个任务2,创建B1实例并跳转。
  ——————–栈顶     ——————–栈顶
  【A】       ——> 【B1】
  ——————–栈底     ——————–栈底
  任务一栈          任务2栈
 B1跳转到A,系统检测所有任务,在任务1栈中发现了A的实例,所以直接跳转。注意,这个时候A的所有信息还保留着,假设用户一开始在A中写了字母“s”,然后跳转到B1,现在从B1跳转回来依然是字母“s”,不会重新实例一个A。
  ——————–栈顶     ——————–栈顶
  【A】        <—— 【B1】
  ——————–栈底     ——————–栈底
  任务一栈          任务2栈
 A跳转到B2,B2是standard启动模式,因为任务1和A不相容,所以系统在任务2中创建了B2,置于栈顶并跳转。
  ——————–栈顶     ——————–栈顶
            ——>  【B2】
  【A】             【B1】
  ——————–栈底     ——————–栈底
  任务一栈          任务2栈
 B2跳转到A和B1跳转到A是一样的过程,就不赘述了,注意A依然不会新实例化。
 最后要从A跳转到B1,系统发现B1在任务2中,但是任务1无法访问任务2非栈顶的Activity(前面提到过原因),只能访问任务2的栈顶Activity即B2,即使B2是standard启动模式依然不会新建一个实例,所以之前在B2修改的数据全部保留。B1依然存在于任务2栈中,所以用户按一次返回键即可以访问到B1。
  ——————–栈顶     ——————–栈顶
            ——>  【B2】
  【A】             【B1】
  ——————–栈底     ——————–栈底
  任务一栈          任务2栈
  
  因此最终无法跳转到B1,如果想要跳到B1,就要另想办法啦,比如设置A为singleTask或者三个activity全部设置为singleInstance等等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值