先来明确两个概念
应用:
应用通常包含多个 Activity。每个 Activity 均应围绕用户可以执行的特定操作设计,并且能够启动其他 Activity。 例如,电子邮件应用可能有一个 Activity 显示新邮件的列表。用户选择某邮件时,会打开一个新 Activity 以查看该邮件。
任务
任务是指在执行特定作业时与用户交互的一系列 Activity。 这些 Activity 按照各自的打开顺序排列在堆栈(即返回栈)中。
管理任务
Android 管理任务和返回栈的方式(如上所述,即:将所有连续启动的 Activity 放入同一任务和“后进先出”堆栈中)非常适用于大多数应用,而您不必担心 Activity 如何与任务关联或者如何存在于返回栈中。 但是,您可能会决定要中断正常行为。 也许您希望应用中的 Activity 在启动时开始新任务(而不是放置在当前任务中);或者,当启动 Activity 时,您希望将其现有实例上移一层(而不是在返回栈的顶部创建新实例);或者,您希望在用户离开任务时,清除返回栈中除根
Activity 以外的所有其他 Activity。
通过使用 <activity> 清单文件元素中的属性和传递给 startActivity() 的 Intent 中的标志来定义启动模式
定义启动模式
在清单文件中声明 Activity 时,您可以使用 <activity> 元素的 launchMode 属性指定 Activity 应该如何与任务关联。
launchMode 属性指定有关应如何将 Activity 启动到任务中的指令。您可以分配给 launchMode 属性的启动模式共有四种:
"standard"(默认模式)
系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。
launchMode 属性指定有关应如何将 Activity 启动到任务中的指令。您可以分配给 launchMode 属性的启动模式共有四种:
"standard"(默认模式)
系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。
"singleTop"
如果当前任务的顶部已存在 Activity 的一个实例,则系统会通过调用该实例的 onNewIntent() 方法向其传送 Intent,而不是创建 Activity 的新实例。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例(但前提是位于返回栈顶部的 Activity 并不是 Activity 的现有实例)。例如,假设任务的返回栈包含根 Activity A 以及 Activity B、C 和位于顶部的 D(堆栈是 A-B-C-D;D 位于顶部)。收到针对 D 类 Activity 的 Intent。如果 D 具有默认的 "standard" 启动模式,则会启动该类的新实例,且堆栈会变成 A-B-C-D-D。但是,如果 D 的启动模式是 "singleTop",则 D 的现有实例会通过onNewIntent() 接收 Intent,因为它位于堆栈的顶部;而堆栈仍为 A-B-C-D。但是,如果收到针对 B 类 Activity 的 Intent,则会向堆栈添加 B 的新实例,即便其启动模式为 "singleTop" 也是如此。
"singleTask"
系统创建新任务并实例化位于新任务底部的 Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的onNewIntent() 方法向其传送 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。
注:尽管 Activity 在新任务中启动,但是用户按“返回”按钮仍会返回到前一个 Activity。
"singleInstance".
与 "singleTask" 相同,只是系统不会将任何其他 Activity 启动到包含实例的任务中。该 Activity 始终是其任务唯一仅有的成员;由此 Activity 启动的任何Activity 均在单独的任务中打开。
如果当前任务的顶部已存在 Activity 的一个实例,则系统会通过调用该实例的 onNewIntent() 方法向其传送 Intent,而不是创建 Activity 的新实例。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例(但前提是位于返回栈顶部的 Activity 并不是 Activity 的现有实例)。例如,假设任务的返回栈包含根 Activity A 以及 Activity B、C 和位于顶部的 D(堆栈是 A-B-C-D;D 位于顶部)。收到针对 D 类 Activity 的 Intent。如果 D 具有默认的 "standard" 启动模式,则会启动该类的新实例,且堆栈会变成 A-B-C-D-D。但是,如果 D 的启动模式是 "singleTop",则 D 的现有实例会通过onNewIntent() 接收 Intent,因为它位于堆栈的顶部;而堆栈仍为 A-B-C-D。但是,如果收到针对 B 类 Activity 的 Intent,则会向堆栈添加 B 的新实例,即便其启动模式为 "singleTop" 也是如此。
"singleTask"
系统创建新任务并实例化位于新任务底部的 Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的onNewIntent() 方法向其传送 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。
注:尽管 Activity 在新任务中启动,但是用户按“返回”按钮仍会返回到前一个 Activity。
"singleInstance".
与 "singleTask" 相同,只是系统不会将任何其他 Activity 启动到包含实例的任务中。该 Activity 始终是其任务唯一仅有的成员;由此 Activity 启动的任何Activity 均在单独的任务中打开。
使用 Intent 标志声明启动模式:
启动 Activity 时,您可以通过在传递给 startActivity() 的 Intent 中加入相应的标志,修改 Activity 与其任务的默认关联方式。可用于修改默认行为的标志包括:
FLAG_ACTIVITY_NEW_TASK:在新任务中启动 Activity。如果已为正在启动的 Activity 运行任务,则该任务会转到前台并恢复其最后状态,同时 Activity 会在 onNewIntent()
中收到新 Intent。正如前文所述,这会产生与 "singleTask"launchMode 值相同的行为。
FLAG_ACTIVITY_SINGLE_TOP:如果正在启动的 Activity 是当前 Activity(位于返回栈的顶部),则 现有实例会接收对 onNewIntent() 的调用,而不是创建 Activity 的新实例。
正如前文所述,这会产生与 "singleTop"launchMode 值相同的行为。
FLAG_ACTIVITY_NEW_TASK:在新任务中启动 Activity。如果已为正在启动的 Activity 运行任务,则该任务会转到前台并恢复其最后状态,同时 Activity 会在 onNewIntent()
中收到新 Intent。正如前文所述,这会产生与 "singleTask"launchMode 值相同的行为。
FLAG_ACTIVITY_SINGLE_TOP:如果正在启动的 Activity 是当前 Activity(位于返回栈的顶部),则 现有实例会接收对 onNewIntent() 的调用,而不是创建 Activity 的新实例。
正如前文所述,这会产生与 "singleTop"launchMode 值相同的行为。
(注:如果两种模式都存在,以第二种方式为准。)
详细解析一下这四种模式
1、standard:标准模式,也是默认模式。每次启动一个Activity都会重新创建一个实例,不管这个实例是否存在。这是一种典型的多实例实现,一个任务栈可以有多个实例,每个实例也可以属于不同的任务栈。比如:在Activity A中启动了Activity B,那么B就会进入到A所在的任务栈中,在Activity B中又启动Activity A ,那么A又会进入任务栈中(Activity A和Activity B都是standard模式)。如图:
图中三个Activity启动模式都是standard模式
从上图我们可以看出:standard模式下启动的Activity可以一直被创建,并进入任务栈中;要注意的是当我们启动新的Activity时,旧的Activity要先执行onPause方法,然后新的Activity才会创建,当新的Activity完全可见时,旧的Activity才会执行onStop方法。
2、singleTop:栈顶复用模式。在这模式下,如果Activity已经位于任务栈的栈顶,那么该Activity将不会被重新创建。比如,目前任务栈内有Activity A,在Activity A中启动Activity B,任务栈中会有A、B。如果再启动B,任务栈中任是A、B。其中B的启动模式为singleTop,如图:
(注如下图,图中三个Activity启动模式都是singleTop模式:)
上图可知:如果Activity已经位于栈顶,那么此Activity就不会被创建。需要注意的是此时你启动栈顶Activity时,这个Activity的onCreate和onStart方法不会被系统调用,因为它们并没有发生改变。
3、singleTask:栈内复用模式。在这种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例。
①如果当前任务栈S1有ABCD四个Activity,这个时候B以singleTask模式请求启动,那么任务栈会将B以上的Activity实例全部出栈,此时S1任务栈中的情况为AB。
②如果目前任务栈S1有ABC三个Activity,这个时候D以singleTask模式请求启动,其所需要的任务栈为S2(指定了任务栈),由于S2和D的实例都不存在,所以系统会先创建任务栈S2,然后再创建D的实例并将其入栈到S2。
③如果目前任务栈S1有ABC三个Activity,这个时候D以singleTask模式请求启动,其所需要的任务栈为S1。由于S1已经存在,系统会直接创建D的实例并将其入栈到S1。
如图:
①如果当前任务栈S1有ABCD四个Activity,这个时候B以singleTask模式请求启动,那么任务栈会将B以上的Activity实例全部出栈,此时S1任务栈中的情况为AB。
②如果目前任务栈S1有ABC三个Activity,这个时候D以singleTask模式请求启动,其所需要的任务栈为S2(指定了任务栈),由于S2和D的实例都不存在,所以系统会先创建任务栈S2,然后再创建D的实例并将其入栈到S2。
③如果目前任务栈S1有ABC三个Activity,这个时候D以singleTask模式请求启动,其所需要的任务栈为S1。由于S1已经存在,系统会直接创建D的实例并将其入栈到S1。
如图:
4. singleInstance:单实例模式。这是一直加强的singleTask模式,它除了具有singleTask模式的所以特性以外,还加强了一点,那就是具有这种模式的Activity只能单独地位于一个任务栈中。
如图(B为singleInstance模式):
如图(B为singleInstance模式):
以上就是四种启动模式的区别。