launchMode,通俗点说,就是定义了Activity应该如何被launch的。那么这几种模式的区别以及应用场景,会有何不一样呢?谷歌是基于什么缘由设计这几种模式的呢?这几种模式背后的工做原理是什么呢?app
在讲解launchMode以前,先说说任务(Task)和返回栈(Back Stack,有些译做回退栈、任务栈)这两个概念。post
A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack—the back stack—in the order in which each activity is opened.设计
任务是指当完成一个特定的工做时与用户交互的一系列Activity。这些Activity按照打开的顺序存放在一个栈中,即返回栈。orm
经过定义能够知道,Activity会被按照打开的顺序存放。不难猜测,这种存放方式,是为了方便回退操做,也就不难解释为何要用栈去存放。排序
当用户点击启动app的时候,这个app的返回栈就会跑到前台,若是这个返回栈不存在的话,就会建立一个。当前Activity启动另外一个Activity的时候,新的Activity就会入栈,在栈顶。若是用户点击返回按钮,当前的Activity就会出栈并销毁,以前的Activity就会被resume,若是栈为空,就会被销毁掉。栈中的Activity永远都不会被从新排序。生命周期
返回栈根据是否在前台,能够分为在前台显示的返回栈,和置于后台的返回栈。其中,置于后台的返回栈中全部的Activity都处于stop状态,用户能够手动的去切换先后台的返回栈状态。内存
当系统内存不足时,系统会优先销毁处于后台的Activity。那么问题来了。后台销毁Activity的优先级是怎样的呢?是将一个返回栈中的Activity都销毁了事后,再去销毁另外一个,仍是说,只是单纯的按照Activity来销毁回收呢?get
任务以及返回栈的管理,能够经过一系列的参数设置来进行,包括咱们本文讲解的launchMode,也是任务管理的一种方式。博客
TaskAffinity即任务相关性,标识一个Activity所须要的返回栈的名字。默认状况下是包名。设置了相同taskAffinity属性的Activity会被放进同一个栈中。一个返回栈的相关性(affinity)是由这个栈的根Activity的相关性(affinity)决定的。it
taskAffinity属性主要与singleTask或allowTaskReparenting结合使用,在其余状况下,这个属性没有做用。这是为何呢?
它的主要做用是Activity的迁移,从一个栈迁移到另外一个栈,这个迁移跟Activity的taskAffinity有关。
这个属性用来清除回退栈中除了根Activity的全部Activity,只对根Activity起做用。当设置为true时,每次从新进入app,只会看到根Activity。
这个属性与clearTaskOnLaunch相反,它是将本Activity移除出去,而不影响其余的Activity。
这个属性的做用是保存返回栈的状态,只对根Activity起做用。正常状况下,系统清理一个返回栈,会将根Activity之上的全部Activity都清除掉。设置该属性后,系统会保存当前的状态。
启动模式主要的做用是什么呢?根据上面对任务及返回栈的介绍,它的做用是定义,一个新的Activity实例如何与当前的任务相关联。它自己是任务的管理方式。
启动模式有两种定义方式,manifest里定义和intent flag的方式。一种是相似配置式的,一种是代码层面的。能够大体推测,确定是带么层面的优先级高一些,可是代码方式劣处就是不启动Activity就没法设置。Android中这种通常提供动态以及静态方式的,套路都大体相同,一些区别各类优劣等。
其中manifest设置与intent flag中都包含对方没有的方式。这也是二者的一个区别。
此处的launchMode专指Activity的launchMode属性。其中有四种方式,这四种方式想必你们也都很清楚了,在这里我不详细展开了。
最多见的一种模式,Activity的默认模式,每次启动该模式的Activity,都会被从新建立,能够从属不一样的任务,也能够在一个任务中被建立屡次。
它的应用场景特别普遍, 通常不是特殊需求的话,都会去使用这种模式。
若是在当前任务的栈顶,系统会调用Activity的onNewIntent()方法而不是从新建立一个新的实例。当用户点击返回键时,当前Activity会被出栈,而不是会退到onNewIntent()以前的状态。
它的应用场景也有一些。例如搜索页面,每次打开,搜索一些结果,点击详情页面,而后继续搜索。在比方说,经过通知打开的页面,若是该页面存在,则更新,若是不存在,则建立。
该模式只容许系统中存在一个该Activity的实例,若是当前实例不存在,则建立,若是已经存在,则将该实例之上的Activity所有出栈,走onNewIntent()。
singleTask适合做为程序入口点,当经过其余方式调用app时候,不会反复建立主页面。例如通常状况下的MainActivity,其余app调用的时候。
这种模式与singleTask十分相似,区别在于,持有该Activity的任务中只能包含一个Activity即它自己。
singleInstance适合须要与程序分离开的页面,例如闹钟的响铃界面,与闹钟的设置相分离。再例如系统的拨号界面。
此处讨论的是经过代码方式进行设置,常见的有以下三种方式。
使用一个新的返回栈来启动Activity,跟上面讨论的singleTask相似
跟上面讨论的singleTop相似
这种方式是上面讨论的launchMode中不存在的,它与singleTop的区别是,当已存在该实例了,会将它之上的Activity都出栈。
它常常与FLAG_ACTIVITY_NEW_TASK组合使用,能够达到singleTask的做用。
几种模式的区别以及应用场景,会有何不一样呢?
答案见上面关于launchMode
谷歌是基于什么缘由设计这几种模式的呢?
关于这个问题,咱们先倒着来推理,即从使用场景去考虑,通常情况下,咱们打开一个页面,不在乎是不是惟一,这个是最多见的需求,所以有了standard模式,这种也是默认的模式。当咱们用搜索页面,当最顶层是搜索页面的时候,我不但愿再打开一个搜索页面,因而有了singleTop模式。当从其余App调用咱们的app的时候,我只但愿只显示一个主页面时,因而有了singleTask。关于singleInstance模式,则是但愿与当前的页面分离。
可是,我以为谷歌并不能列举出全部的场景,例如,我但愿打开一个页面,记录当前的路径,例如a->b->c,这种场景下,四种模式里面没有包含。
若是从正面去推导的话,几种启动模式是任务及返回栈的管理。根据在栈中的状态,大体能够分为以下几类:
是否是很明晰了,有没有其余的出现形式?确定有的,例如栈底惟一,栈中惟一。可是这种方式能够等同于当前栈中惟一啊。
咱们是否能够推导出,谷歌是根据惟一性,来将启动模式分为这几种呢?intent flags则做为辅助的一些操做,例如部分出栈等等。固然这些也只是个人推测,不必定准确,哈哈。
这几种模式背后的工做原理是什么呢?
见任务及返回栈
内存回收的方式,是以Activity仍是以任务做为基准回收?
目前已知的情况时,若是返回栈置于后台,当内存不足的时候,若是不设置alwaysRetainTaskState属性的话,会将除了根Activity的全部Activity销毁掉。能够肯定是以返回栈为基准来进行回收。
taskAffinity属性为何与singleTask一块儿使用才生效?
能够将Activity的launchMode根据是否在栈中惟一分为两类
第一类由于其惟一性,确定是与taskAffinity不兼容的。singleInstance建立的栈中只能包含自己,默认状况下都会单首创建一个栈,指定与否都会单首创建,所以设置没有意义。而singleTask则是当前栈中惟一,适合做为根Activity,建立一个新的栈,这也是为何taskAffinity只能对根Activity起做用的缘故。
我写的内容不必定正确,一些问题的解释也是根据我看到的资料来推到出来的,例如Activity为何会有四种启动模式,若是你们有准确地答案,但愿告知。另外,文中错误的地方,也但愿指正。
最后,感谢你们的浏览,但愿对您有所帮助。