Task和BackStack

2019-07-29  本文已影响0人  wind_sky

一个Android应用通常包含多个Activity,每个Activity均应围绕用户可以进行的特定操作设计,并且能够启动其他Activity。

任务(Task)是指在执行特定作业时与用户交互的一系列Activity,这些Activity按照各自的打开顺序排列在堆栈中(即返回栈BackStack)。

手机的主页是大多数Task的起点,当用户点击应用图标时,该应用的Task将出现在前台,如果应用不存在Task,则会创建一个新Task,并且该应用中的主Activity会作为堆栈中的根Activity打开。

当前 Activity 启动另一个 Activity 时,该新 Activity 会被推送到堆栈顶部,成为焦点所在。 前一个 Activity 仍保留在堆栈中,但是处于停止状态。Activity 停止时,系统会保持其用户界面的当前状态。 用户按“返回”按钮时,当前 Activity 会从堆栈顶部弹出(Activity 被销毁),而前一个 Activity 恢复执行(恢复其 UI 的前一状态)。 堆栈中的 Activity 永远不会重新排列,仅推入和弹出堆栈:由当前 Activity 启动时推入堆栈;用户使用“返回”按钮退出时弹出堆栈。 因此,返回栈以“后进先出”对象结构运行。


image.png

上图展示了back stack的一个工作过程。当所有Activity都从栈中弹出后,Task也不复存在。

任务是一个有机整体,当用户开始新任务或通过“主页”按钮转到主屏幕时,可以移动到“后台”。 尽管在后台时,该任务中的所有 Activity 全部停止,但是任务的返回栈仍旧不变,也就是说,当另一个任务发生时,该任务仅仅失去焦点而已。

注:后台可以同时运行多个任务。但是,如果用户同时运行多个后台任务,则系统可能会开始销毁后台 Activity,以回收内存资源,从而导致 Activity 状态丢失。请参阅下面有关 Activity 状态的部分。

Activity的启动模式:

启动模式允许程序定义 Activity 的新实例如何与当前任务关联。 我们可以通过两种方法定义不同的启动模式:

(1)在manifest文件中定义

在清单文件中声明 Activity 时,您可以使用 <activity> 元素的 launchMode 属性指定 Activity 应该如何与任务关联。launchMode 属性指定有关应如何将 Activity 启动到任务中的指令。您可以分配给 launchMode 属性的启动模式共有四种:

:尽管 Activity 在新任务中启动,但是用户按“返回”按钮仍会返回到前一个 Activity。

我们再来看另一示例,Android 浏览器应用声明网络浏览器 Activity 应始终在其自己的任务中打开(通过在 <activity> 元素中指定 singleTask 启动模式)。这意味着,如果应用发出打开 Android 浏览器的 Intent,则浏览器的 Activity 与应用位于不同的任务中。同时,系统会为浏览器启动新任务,或者如果浏览器已有任务正在后台运行,则会将该任务上移一层以处理新 Intent。

无论Activity是在新任务中启动,还是在与启动它的Activity相同任务中启动,用户点“返回”都会转到前一个Activity。但是,如果Activity的模式是singleTask,则当后台任务存在该Activity实例时,整个任务都会转移到前台,此时返回栈包含上移到栈顶的所有Activity,如下图。


image.png

如需了解有关在清单文件中使用启动模式的详细信息,请参阅 <activity> 元素文档,其中更详细地讨论了 launchMode 属性和可接受的值。

:使用 launchMode 属性为 Activity 指定的行为可由 Intent 附带的 Activity 启动标志替代,下文将对此进行讨论。

(2)使用Intent标志

在启动Activity时,可以通过传递给startActivity的Intent中加入相关的flag,修改Activity与其任务的默认关联方式,比如下面这些flag:

启动 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_CLEAR_TOP

如果正在启动的 Activity 已在当前任务中运行,则会销毁当前任务顶部的所有 Activity,并通过 onNewIntent() 将此 Intent 传递给 Activity 已恢复的实例(现在位于顶部),而不是启动该 Activity 的新实例。

产生这种行为的 launchMode 属性没有值。

FLAG_ACTIVITY_CLEAR_TOP 通常与 FLAG_ACTIVITY_NEW_TASK 结合使用。一起使用时,通过这些标志,可以找到其他任务中的现有 Activity,并将其放入可从中响应 Intent 的位置。

:如果指定 Activity 的启动模式为 "standard",则该 Activity 也会从堆栈中移除,并在其位置启动一个新实例,以便处理传入的 Intent。 这是因为当启动模式为 "standard" 时,将始终为新 Intent 创建新实例。

TaskAffinity:

TaskAffinity指示Activity优先属于哪个任务,默认情况下,同一应用的所有Activity具有相同的TaskAffinity,那就是包名,不过我们可以修改TaskAffinity,可以让不同应用的Activity拥有相同的TaskAffinity也可以让同一个应用有不同的TaskAffinity。通过 <activity> 元素的 taskAffinity 属性(是一个字符串值)修改任何给定 Activity 的关联。

在两种情况下,关联会起作用:

清理Back Stack:

如果用户长时间离开任务,则系统会清除所有 Activity 的任务,根 Activity 除外。 当用户再次返回到任务时,仅恢复根 Activity。系统这样做的原因是,经过很长一段时间后,用户可能已经放弃之前执行的操作,返回到任务是要开始执行新的操作。

我们可以使用下列几个 Activity 属性修改此行为:

上一篇下一篇

猜你喜欢

热点阅读