Android 加载模式

元素的launchMode 属性可以设置四种不同的加载模式:

“standard” (默认值)

“singleTop”

“singleTask”

“singleInstance”

这些模式之间的差异主要体现在四个方面:
• 哪个任务会把持对intent做出响应的activity。对“standard”和“singleTop”模式而言,是产生intent(并调用startActivity())的任务──除非Intent 对象包含FLAG_ACTIVITY_NEW_TASK 标记。而在这种情况下,如同上面Affinitie 和新任务一节所述,会是另外一个任务。

相反,对“singleTask”和“singleInstance”模式而言,activity 总是位于任务的根部。

正是它们定义了一个任务,所以它们绝不会被载入到其它任务之中。

• activity是否可以存在多个实例。一个“standard”或“singleTop”的 activity可以被多次初始化。它们可以归属于多个任务,而一个任务也可以拥有同一activity 的多个实例。

相反,对“singleTask”和“singleInstance”的activity 被限定于只能有一个实例。

因为这些activity 都是任务的起源,这种限制意味着在一个设备中同一时间只允许存在一个任务的实例。

• 在实例所在的任务中是否会有别的activity。一个“singleInstance”模式的 activity将会是它所在的任务中唯一的activity。如果它启动了别的activity,那个activity 将会依据它自己的加载模式加载到其它的任务中去──如同在intent 中设置了FLAG_ACTIVITY_NEW_TASK 标记一样的效果。在其它方面,“singleInstance”模式的效果与“singleTask”是一样的。

剩下的三种模式允许一个任务中出现多个activity。“singleTask”模式的activity 将是任务的根activity,但它可以启动别的activity 并将它们置入所在的任务中。

“standard”和“singleTop”activity 则可以在堆栈的任意位置出现。

• 是否要载入新的类实例以处理新的intent。对默认的"standard"模式来说,对于每个新 intent都会创建一个新的实例以进行响应,每个实例仅处理一个intent。“singleTop”模式下,如果activity 位于目的任务堆栈的最上面,则重用目前现存的activity 来处理新的intent。

如果它不是在堆栈顶部,则不会发生重用。而是创建一个新实例来处理新的intent 并将其推入堆栈。

举例来说,假设一个任务的堆栈由根activityA 和activity B、C 和位于堆栈顶部的D 组成,即堆栈A-B-C-D。

一个针对D 类型的activity 的intent 抵达的时候,如果D 是默认的“standard”加载模式,则创建并加载一个新的类实例,于是堆栈变为A-B-C-D-D。

然而,如果D 的载入模式为“singleTop”,则现有的实例会对新intent 进行处理(因为它位于堆栈顶部)而堆栈保持A-BC-D 的形态。

换言之,如果新抵达的intent 是针对B 类型的activity,则无论B 的模式是“standard”还是“singleTop” ,都会加载一个新的B 的实例(因为B 不位于堆栈的顶部),而堆栈的顺序变为A-B-C-D-B。

如前所述,“singleTask”或“singleInstance”模式的activity 永远不会存在多于一个实例。

所以实例将处理所有新的intent。一个“singleInstance”模式的activity 永远保持在堆栈的顶部(因为它是那个堆栈中唯一的一个activity),所以它一直坚守在处理intent 的岗位上。

然而,对一个“singleTask”模式的activity 来说,它上面可能有,也可能没有别的activity 和它处于同一堆栈。

在有的情况下,它就不在能够处理intent 的位置上,则那个intent 将被舍弃。(即便在intent 被舍弃的情况下,它的抵达仍将使这个任务切换至前台,并一直保留)当一个现存的activity 被要求处理一个新的intent 的时候,会调用onNewIntent()方法来将intent 对象传递至activity。

(启动activity 的原始intent 对象可以通过调用getIntent()方法获得。)

请注意,当一个新的activity 实例被创建以处理新的intent 的时候,用户总可以按下BACK 键来回到前面的状态(回到前一个activity)。但当使用现存的activity 来处理新intent 的时候,用户是不能靠按下BACK 键回到当这个新intent 抵达之前的状态的。