【磨叽教程】Android进阶之玩转任务栈——启动方式详解

在上文中我们介绍了任务栈,这节讨论一下怎么使用并掌握它。

回顾上节:Android 管理任务和返回堆栈的方式是将所有接连启动的 Activity 放到同一任务和一个“后进先出”堆栈中。
我们不需要关注任务栈和Activity是怎么关联的,但是如果我们要想突破这种约定成俗的套路就需要了解本节课的主要内容了。
比如说:你希望应用中的某个 Activity 在启动时开启一个新的任务(而不是被放入当前的任务中),或者当你启动某个 Activity 时,希望调用它的一个现有实例(而不是在返回堆栈顶部创建一个新实例),或者希望在用户离开任务时清除返回堆栈中除根 Activity 以外的所有 Activity。

如果想实现上述目的,我们可以先讨论以下两个方法:

1、使用清单文件中的属性定义
2、在启动的时候给Intent做标记

使用清单文件

在清单文件中声明 Activity 时,可以使用 元素的 launchMode 属性指定 Activity 应该如何与任务关联。

launchMode 属性说明了 Activity 应如何启动到任务中。

launchMode 属性指定 4 种不同的启动模式:

"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” 也是如此。

注意:创建 Activity 的新实例后,用户可以按返回按钮返回到上一个 Activity。但是,当由 Activity 的现有实例处理新 intent 时,用户将无法通过按返回按钮返回到 onNewIntent() 收到新 intent 之前的 Activity 状态。

"singleTask"
系统会创建新任务,并实例化新任务的根 Activity。但是,如果另外的任务中已存在该 Activity 的实例,则系统会通过调用其 onNewIntent() 方法将 intent 转送到该现有实例,而不是创建新实例。Activity 一次只能有一个实例存在。

注意:虽然 Activity 在新任务中启动,但用户按返回按钮仍会返回到上一个 Activity。

"singleInstance"
与 “singleTask” 相似,唯一不同的是系统不会将任何其他 Activity 启动到包含该实例的任务中。该 Activity 始终是其任务唯一的成员;由该 Activity 启动的任何 Activity 都会在其他的任务中打开。

举个例子,Android 浏览器应用在 元素中指定 singleTask 启动模式,由此声明网络浏览器 Activity 应始终在它自己的任务中打开。这意味着,如果应用发出打开 Android 浏览器的 intent,系统不会将其 Activity 置于应用所在的任务中,而是会为浏览器启动一个新任务,如果浏览器已经有任务在后台运行,则会将该任务转到前台来处理新 intent。
无论 Activity 是在新任务中启动的,还是在和启动它的 Activity 相同的任务中启动,用户按返回按钮都会回到上一个 Activity。但是,如果您启动了指定 singleTask 启动模式的 Activity,而后台任务中已存在该 Activity 的实例,则系统会将该后台任务整个转到前台运行。此时,返回堆栈包含了转到前台的任务中的所有 Activity,这些 Activity 都位于堆栈的顶部。

【磨叽教程】Android进阶之玩转任务栈——启动方式详解_第1张图片

图 示. 采用“singleTask”启动模式的 Activity 添加到返回堆栈的过程图示。如果 Activity 已经存在于某个具有自己的返回堆栈的后台任务中,那么整个返回堆栈也会转到前台,覆盖当前任务。

使用Intent标记

启动 Activity 时,可以在传送给 startActivity() 的 intent 中添加相应的标记来修改 Activity 与其任务的默认关联。

下面着重讨论三种标记:

FLAG_ACTIVITY_NEW_TASK

在新任务中启动 Activity。如果启动的 Activity 已经有任务在运行,则系统会将该任务转到前台并恢复其最后的状态,而 Activity 将在 onNewIntent() 中收到新的 intent。

这与上面介绍的 “singleTask” launchMode 值产生的行为相同。

FLAG_ACTIVITY_SINGLE_TOP

如果要启动的 Activity 是当前 Activity(即位于返回堆栈顶部的 Activity),则现有实例会收到对 onNewIntent() 的调用,而不会创建 Activity 的新实例。

这与上一节中介绍的 “singleTop” launchMode 值产生的行为相同。

FLAG_ACTIVITY_CLEAR_TOP

如果要启动的 Activity 已经在当前任务中运行,则不会启动该 Activity 的新实例,而是会销毁位于它之上的所有其他 Activity,并通过 onNewIntent() 将此 intent 传送给它的已恢复实例(现在位于堆栈顶部)。

launchMode 属性没有可产生此行为的值。

FLAG_ACTIVITY_CLEAR_TOP 最常与 FLAG_ACTIVITY_NEW_TASK 结合使用。将这两个标记结合使用,可以查找其他任务中的现有 Activity,并将其置于能够响应 intent 的位置。(更多内容请关注“计算机自学平台”)

注意:如果指定 Activity 的启动模式为 “standard”,系统也会将其从堆栈中移除,并在它的位置启动一个新实例来处理传入的 intent。这是因为当启动模式为 “standard” 时,始终会为新 intent 创建新的实例。

你可能感兴趣的:(磨叽教程—Android进阶)