android singleTask 活动不作为根?

Posted

技术标签:

【中文标题】android singleTask 活动不作为根?【英文标题】:android singleTask activity not as the root? 【发布时间】:2016-02-29 20:11:47 【问题描述】:

我一直在阅读有关启动模式的文档,但有一件事我不明白。 doc 表示 singleTask 活动始终是堆栈的根:

相比之下,“singleTask”和“singleInstance”活动只能 开始一项任务。 它们始终位于活动堆栈的根部。 此外,该设备在同一时间只能保存一个活动实例 时间——只有一项这样的任务。

但是:如果您查看Figure 4 的文档的this 部分,您会看到当 Activity 2 启动 Activity Y(将该任务置于前台)时,Activity Y 已经在任务的顶部并且将在当前任务的顶部,而不是根目录。

我在simulation app 中尝试了这个场景,当我创建 singleTask 活动时,它总是会创建一个新任务。但是,如果唯一的实例已经存在,它会完成高于该实例的所有活动,因此唯一的实例可以是根(也是任务中的唯一活动)。

Activity Y 怎么会成为 Activity X 之上任务的顶部?

我还有什么其他原因吗?

PS:我也不太明白Task和back stack的区别。

【问题讨论】:

【参考方案1】:

像往常一样(叹气),文档是错误的。在您引用的图表中,显然 Activity Y 不能定义为 singleTask 并且是包含 2 个活动的后台任务中的***活动。

在测试具有特殊启动模式singleTasksingleInstance 的场景时,请注意taskAffinity 在此行为中起着重要作用,因为taskAffinity 优先于特殊启动模式。


关于“任务”和“回栈”的区别:

“任务”是一组可以作为一个整体进行操作的活动。

当您启动应用程序时(假设它当前未运行),android 会在前台创建一个新任务,其中包含您启动的应用程序的根 Activity。 当该活动开始新活动时,这些新活动将添加到当前任务中(通常情况下,尽管此行为有例外)。 当您按下 HOME 按钮时,当前任务将从前台移至后台。 当您显示“最近”列表时,显示的是最近任务列表,而不是最近活动列表或最近应用程序列表。 当您从最近的任务列表中选择一个任务时,如果该任务仍处于活动状态(其中仍有活动活动),则整个任务(包括其所有活动)将从后台带到前台。 任务也可以“堆叠”。当当前任务中的活动启动新任务中的活动时,新任务会堆叠在当前任务之上。这仅用于控制新任务完成时发生的情况。通常情况下,当新任务完成(其所有活动都已完成)时,Android 会将用户返回到上一个任务(即:开始完成任务的任务)。

“回栈”通常是指任务中的一组活动。每个任务都有自己的活动堆栈。这用于控制当前活动(位于后台堆栈顶部的活动)完成时会发生什么。通常,Android 会将用户返回到直接位于后堆栈中完成活动下方(下方)的活动。

Android 代码和文档经常提到任务的“根”(这是用于启动任务的 Activity)和任务的“顶部”或“前端”(这是目前正在显示)。


实际上,文档位于 :-( 这是一个示例:

相比之下,“singleTask”和“singleInstance”活动只能 开始一项任务。

这种说法通常是正确的,但并不总是正确的。例如,假设我有 2 个活动:ABA 是启动活动(即:具有ACTION=MAINCATEGORY=DEFAULT 的活动)并使用标准启动模式定义。 B 定义为 launchMode="singleTask"。我启动应用程序,Android 创建了一个A 的实例。然后在A 做:

startActivity(new Intent(this, B.class));

这将创建一个新的活动实例B 并将其放在同一任务中的A 之上。它不会创建以活动B 为根的新任务。原因是activityA和activityB具有相同的taskAffinity(默认情况下一个应用的所有activity都具有相同的taskAffinity),此时Android会忽略B的启动模式。

文档还说:

此外,设备一次只能保存一个活动实例 时间——只有一项这样的任务。

同样,taskAffinity 可以打破这种行为。再次假设我们有ABC,它们都具有相同的(默认)taskAffinityAC 具有标准启动模式,B 具有 launchMode="singleTask"。如果A 启动BB 的实例不会在新任务中结束,而是在与A 相同的任务中(见上文)。现在B 开始C。 Android 创建C 的实例并将其放在同一任务中的B 之上。现在C打电话:

startActivity(new Intent(this, B.class));

Android 会创建一个 B 的新实例,并将其置于任务中的 C 之上。现在有 2 个 B 实例,它们都不是任务的根活动!这种行为也是因为taskAffinity 胜过启动模式。

【讨论】:

感谢您的差异!但是你描述的亲和力仍然让我想知道。如果我在原始帖子中指定的应用程序中尝试您的第一个示例,它会按预期运行 - 创建新任务。为了对应你所说的......他们必须改变亲和力才能获得这种行为?我对此表示怀疑。 你是对的。我创建了一个示例项目,它按您所说的那样工作。我猜他们真的不得不改变亲和力。或者只是不同的包名就足够了? (我通常将所有活动都放在同一个包中)但是当我想打开新任务时,如何在我的应用程序中完成此行为?我必须在每个活动中指定不同的亲和力吗?这很奇怪。 任务亲和性用于将应该在同一个任务中的活动组合在一起。通常,在单个应用程序中,您会希望所有(或大部分)活动都在同一个任务中。您很少需要创建多个任务。如果您确实需要创建多个任务,则有很多“陷阱”,因为您还需要确保用户能够区分任务之间的差异,以便他可以返回正确的任务。这通常意味着为不同的任务使用不同的应用程序图标和不同的应用程序名称。请描述您为什么需要不同的任务。 我不确定。我有一个登录活动 (A) 在成功登录后完成。然后是 B -> C 其中例如抛出异常。现在我想丢弃 B 和 C 并在不同的任务中显示 A,这样用户就无法返回......这是 taskAffinity 可以发生的场景吗?我读过我可以通过使用带有适当标志的意图来实现这一点。 我无法在同一个任务中使用 launchMode="singleTask" 的同一 Activity 的两个(或更多)实例来重现该案例。启动一个已经在堆栈中有一个的新实例只会打开现有的 Activity,同时清除堆栈的顶部。所有活动的任务关联性都是相同的。

以上是关于android singleTask 活动不作为根?的主要内容,如果未能解决你的问题,请参考以下文章

Android singleTask 还是 singleInstance 启动模式? [关闭]

Android:恢复 singleTask 活动

Activty四种启动模式

Android中维护标准应用Activity回栈状态(使用singleTask启动模式)

SingleTask 活动在同一个进程中多次创建

即使使用 launchMode="singleTask" 也可以启动两次活动