Activity启动模式

记得刚开始学习android开发的时候,有一次在demo中,多次启动了同一个Activity。然后在点击物理返回键的时候,发现那个Activity出现了很多次。当时在想,能不能不管我启动了多少次这个Activity,在栈中只保留它的一个实例。当时带着这个问题去找度娘,度娘告诉了我一个新的概念叫做:Activity的启动模式

学习之前先要了解的概念

(1)Activity任务栈

Activity任务栈又称为task,是存放Activity的容器,其内部遵循先进后出的原则。每当我们打开一个Activity的时候它会往Activity任务栈中压入一个Activity,每当我们销毁一个Activity的时候它会从Activity任务栈中弹出一个Activity,在Android系统中,我们只能在手机屏幕上获取任务栈最上面的Activity的焦点(即栈顶元素),其余的Activity会暂居后台等待系统调用。一般情况下,同一个应用程序的activity都属于同一个任务栈。任务栈可以分为前台任务栈和后台任务栈,后台任务栈中的Activity处于暂停状态,用户可以通过切换将后台的任务栈调回到前台。

注意:一个Task中的Actvity可以来自不同的App,同一个App的Activity也可能不在一个Task中。这就是我们接下来要讲的TaskAffinity所做的事情

(2)TaskAffinity

google给的翻译是:任务亲和力。通过这个参数,我们可以给一个Activity设置其所需的任务栈的名字。默认情况下,应用的任务栈的名字为其包名,所以TaskAffinity不能与包名相同。这个属性值一般与singleTask或者allowTaskReparenting配合使用。Task也有affinity属性,它的affinity属性由根Activity(创建Task时第一个被压入栈的Activity)决定。

allowTaskReparenting属性如果为true,则会发生这么一种情况:应用X中有一个allowTaskReparenting属性为true的Activity A,如果我们从应用Y中启动了Activity A,此时,Activity A应该是位于启动它的应用Y的任务栈中。这个时候,我们按Home键返回到桌面,点击应用X的启动图标,会发现应用X不是启动了主Activity,而是启动了Activity A。

Activity的四种启动模式

Activity的启动模式有四种模式,分别为standard、singleTop、singleTask及singleInstance。我们可以设置启动模式或者标志位,来为Activity指定其启动模式。接下来,我们先看一下这四个启动模式分别代表什么。

###(1)standard(默认的启动模式)

这是Acticity默认的启动模式,我们如果不做其他设置,则Activity使用这种模式。在standard模式下,每启动一个Activity,就会在任务栈中创建一个实例,不管该实例是否存在。在这种模式下,被启动的Activity会和启动它的Activity处于同一个任务栈。

在工作中我们会发现,如果使用ApplicationContext去启动standard模式的Activity会报错,这就是因为非Activity类型的context没有所谓的任务栈。那么怎么解决这个问题呢?我们接下来讲到标志位的时候会告诉大家。

(2)singleTop

栈顶复用模式。在这个模式下,如果在任务栈的栈顶存在被启动的Activity的实例,则被启动的Activity不会新建实例,而是复用栈顶的实例。比如如果目前栈内的情况为A–>B–>C,A、B、C都是singleTop模式,A在栈底,C在栈顶。此时我们再次启动C,因为栈顶存在C的实例,所以C不会被创建,而是复用栈顶的C的实例。而如果我们启动的是A呢?因为A虽然在栈内,但是并不是位于栈顶,所以,A的实例还会被创建,此时栈内的情况就A–>B–>C–>A。

(3)singleTask

栈内复用模式。在这种模式下,如果栈内存在要启动的Activity的实例,则系统会将其上方的其他Activity出栈,以使其位于栈顶,而不会去重新创建此Activity的实例。比如当前栈内Activity为A–>B–>C,此时,启动一个singleTask模式的Activity D,因为栈内没有Activity D,所以,Activity D会被压入栈中,此时栈内Activity为A–>B–>C–>D。但是,如果当前栈内Activity为A–>D–>B–>C,此时启动一个singleTask模式的Activity D。因为栈内存在Activity D的实例,所以位于Activity D上方的Activity出栈,将Activity D提到栈顶。此时栈内Activity为A–>D。

(4)singleInstance

单实例模式。具有此种启动模式的Activity只能单独位于一个任务栈中。并且之后的请求均不会创建新的实例。除非其所处的任务栈被销毁。

好了,启动模式就介绍完了,那么如何给一个Activity设置启动模式呢?

####(1)静态设置(清单文件)

在清单文件中给Activity设置launchMode属性,指定Activity的启动模式。

####(2)动态设置(标志位)

在代码中,通过在Intent中设置标志位(intent.setFlags(flag);)来指定Activity的启动模式。我们看一下几个比较重要的标志位:

1.FLAG_ACTIVITY_NEW_TASK:

当Intent对象包含这个标记时,系统会寻找或创建一个新的task来放置目标Activity,寻找时依据目标Activity的taskAffinity属性进行匹配,如果找到一个task的taskAffinity与之相同,就将目标Activity压入此task中,如果查找无果,则创建一个新的task,并将该task的taskAffinity设置为目标Activity的taskActivity,将目标Activity放置于此task。

这就是我们上面所说的解决非Activity类型的Conext启动Activity报错的方法。为待启动的Activity指定此标志位,则在启动时会为他创建一个新的任务栈。

2.FLAG_ACTIVITY_CLEAR_TOP:

当Intent对象包含这个标记时,如果在栈中发现存在Activity实例,则清空这个实例之上的Activity,使其处于栈顶。在使用默认的“standard”启动模式下,如果没有在Intent使用到FLAG_ACTIVITY_SINGLE_TOP标记,那么它将关闭后重建,如果使用了这个FLAG_ACTIVITY_SINGLE_TOP标记,则会使用已存在的实例;对于其他启动模式,无需再使用FLAG_ACTIVITY_SINGLE_TOP,它都将使用已存在的实例,Intent会被传递到这个实例的onNewIntent()中。

3.FLAG_ACTIVITY_SINGLE_TOP:

与Activity启动模式中的singleTop效果相同。

4.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET:

如果一个Intent中包含此属性,则它转向的那个Activity以及在那个Activity其上的所有Activity都会在task重置时被清除出task。当我们将一个后台的task重新回到前台时,系统会在特定情况下为这个动作附带一个FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记,意味着必要时重置task,这时FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET就会生效。

5.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:

这个标记在以下情况下会生效:1.启动Activity时创建新的task来放置Activity实例;2.已存在的task被放置于前台。系统会根据affinity对指定的task进行重置操作,task会压入某些Activity实例或移除某些Activity实例。

Activity启动模式静态设置和动态设置的区别

(1)优先级:动态设置优先于静态设置

(2)静态设置无法为Activity设置FLAG_ACTIVITY_CLEAR_TOP标识效果相同的启动模式

(3)动态设置无法为Activity指定与singleInstance模式效果相同的标志位

好了,以上就是本文全部内容。写的比较乱,以后注意一下吧。

你可能感兴趣的:(android,移动开发,android,启动模式,task)