Activity的任务栈和四大启动模式

前言

在安卓系统中默认每次启动一个Activity时,系统会创建一个实例,并按照先进后出的原则放入任务栈中,当我们按back键时,就会有一个activity从任务栈顶移除,重复下去,直到任务栈为空,系统就会回收这个任务栈。但是这样以来,系统多次启动同一个Activity时就会重复创建多个实例,这种做法显然不合理,为了能够优化这个问题,Android提供四种启动模式来修改系统这一默认行为。

任务栈

任务栈是一个Android应用中所有Activity的集合,安卓系统使用栈的方式来管理其中的Activity,这个栈又被称为返回栈(back stack),栈中Activity的顺序就是按照它们被打开的顺序依次存放的。

任务栈的特点:
  • 任务栈是记录存放用户开启的activity的。
  • 一个应用程序一被开启系统就给他分配一个任务栈,当所有的activity都退出的时候,任务栈就清空了。
  • 当一个Activity启动了另外一个Activity的时候,新的Activity就会被放置到返回栈的栈顶并将获得焦点。前一个Activity仍然保留在返回栈当中,但会处于停止状态。
  • 当用户按下Back键的时候,栈中最顶端的Activity会被移除掉,然后前一个Activity则会得重新回到最顶端的位置。
  • 任务栈是一个典型的后进先出(last in, first out)的数据结构。只能向栈顶添加Activity,或者将栈顶的Activity移除掉。因此,返回栈
  • 任务栈的id是一个integer的数据类型 自增长的。
  • 在android操作系统里面会存在多个任务栈,一个应用程序一个任务栈。
  • 桌面应用和一般的应用程序是一样的,任务栈的行为也是一样。默认情况下,关闭掉一个应用程序,清空了这个应用程序的任务栈。应用程序的进程还会保留。
  • 程序打开时就创建了一个任务栈,用于存储当前程序的activity,当前程序(包括被当前程序所调用的)所有的activity属于一个任务栈。
  • 一个任务栈包含了一个activity的集合,可以有序的选择哪一个activity和用户进行交互,只有在任务栈栈顶的activity才可以跟用户进行交互。
  • 任务栈可以移动到后台,并且保留了每一个activity的状态.并且有序的给用户列出它们的任务, 而且还不丢失它们状态信息。
  • 退出应用程序时,当把所有的任务栈中所有的activity清除出栈时,任务栈会被销毁,程序退出。
Activity的四种启动模式如下

standard、singleTop、singleTask、singleInstance

  • standard-标准模式
    这个模式是默认的启动模式,即标准模式,在不指定启动模式的前提下,系统默认使用该模式启动Activity,每次启动一个Activity都会重写创建一个新的实例,不管这个实例存不存在,这种模式下,谁启动了该模式的Activity,该Activity就属于启动它的Activity的任务栈中。在standard模式任务栈中无论该活动有没有加入栈,活动都会被创建,这个Activity它的onCreate(),onStart(),onResume()方法都会被调用。

  • singleTop-栈顶复用模式
    这个模式下,如果要启动的Activity已经存在实例在栈顶,那么这个Activity不会被重新创建,而是复用栈顶的实例,并且会将Intent对象传入,回调onNewIntent方法,需要注意的是这个Activity它的onCreate(),onStart()方法不会被调用,因为它并没有发生改变。如果栈顶不存在该Activity的实例,则情况与standard模式相同,创建新的Activity实例。

  • singleTask-栈内复用模式
    这个模式下,如果要启动的Activity在任务栈中存在实例,那么这个Activity不会被重新创建,而是移除(Destory)任务栈中在该实例之上的所有Activity,把目标实例置于栈顶并直接调用它的onNewIntent()方法。若不存在则新建。

在同一个任务栈中只存在一个实例。

  • singleInstance-单例模式
    该模式具备singleTask模式的所有特性外,与它的区别就是,这种模式下的Activity会单独占用一个Task栈,具有全局唯一性,即整个系统中就这么一个实例,由于栈内复用的特性,后续的请求均不会创建新的Activity实例,除非这个特殊的任务栈被销毁了。以singleInstance模式启动的Activity在整个系统中是单例的,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。
taskAffinity属性对singleTask启动模式的影响
  • 什么是affinity?

affinity是指Activity的归属,Activity与Task的吸附关系,也就是该Activity属于哪个Task。一般情况下在同一个应用中,启动的Activity都在同一个Task中,它们在该Task中度过自己的生命。每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于应用的包名。我们可以通过在元素中增加taskAffinity属性来为某一个Activity指定单独的affinity。这个属性的值是一个字符串,可以指定为任意字符串,但是必须至少包含一个”.”,否则会报错。

未设置该属性,则 Activity继承为应用(application)设置的亲和关系;若应用未设置该属性,则默认使用包名作为该属性值;若application和Activity中均设置了该属性,则以Activity中的属性为准。
该属性可以将在不同应用中定义的 Activity 置于同一任务内
将该属性设置为空字符串,可使指定 Activity 与任何任务均无亲和关系。有点像singleInstance的模式。单独使用一个任务栈,且其内只有指定 Activity的一个实例。
该属性要么为空字符串,要么其值之中至少包含一个“.”符号,否则apk无法通过编译安装

taskAffinity在什么场合应用呢?
  • 场景一

根据affinity重新为Activity选择宿主task(与allowTaskReparenting属性配合使用)
allowTaskReparenting用来标记Activity能否从启动的Task移动到taskAffinity指定的Task,当把Activity的allowTaskReparenting属性设置成true时,Activity就拥有了一个转移所在Task的能力。具体点来说,就是一个Activity现在是处于某个Task当中的,但是它与另外一个Task具有相同的affinity值,那么当另外这个任务切换到前台的时候,该Activity就可以转移到现在的这个任务当中。allowTaskReparenting默认是继承至application中的allowTaskReparenting=false,如果为true,则表示可以更换;false表示不可以。

举一个形象点的例子,比如有一个天气预报程序,它有一个用于显示天气信息的Activity,allowTaskReparenting属性设置成true,这个Activity和天气预报程序的所有其它Activity具体相同的affinity值。这个时候,你自己的应用程序通过Intent去启动了这个用于显示天气信息的Activity,那么此时这个Activity应该是和你的应用程序是在同一个任务当中的。但是当把天气预报程序切换到前台的时候,这个Activity会被转移到天气预报程序的任务当中,并显示出来。如果将你自己的应用切换到前台,发现你自己应用Task里的那个Activity消失了。

  • 场景二

启动一个Activity过程中Intent使用了FLAG_ACTIVITY_NEW_TASK标记,根据affinity查找或创建一个新的具有对应affinity的task。当调用startActivity()方法来启动一个Activity时,默认是将它放入到当前的任务当中。但是,如果在Intent中加入了FLAG_ACTIVITY_NEW_TASK flag的话,情况就会变的复杂起来。首先,系统会去检查这个Activity的affinity是否与当前Task的affinity相同。如果相同的话就会把它放入到当前Task当中,如果不同则会先去检查是否已经有一个名字与该Activity的affinity相同的Task,如果有,这个Task将被调到前台,同时这个Activity将显示在这个Task的顶端;如果没有的话,系统将会尝试为这个Activity创建一个新的Task。需要注意的是,如果一个Activity在manifest文件中声明的启动模式是”singleTask”,那么他被启动的时候,行为模式会和前面提到的指定FLAG_ACTIVITY_NEW_TASK一样。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值