4

在关于任务和回栈的官方在线 Android指南中,我发现有一条信息自相矛盾。因此,如果有人可以帮助我解决这个问题,我将不胜感激。

首先,有以下声明:

堆栈中的 Activity 永远不会重新排列,只会从堆栈中压入和弹出——当当前 Activity 启动时将其压入堆栈,并在用户使用“后退”按钮离开时弹出。

然后描述了singleTask的启动方式,有如下语句:

系统创建一个新任务并在新任务的根部实例化活动。但是,如果活动的实例已经存在于单独的任务中,系统将通过调用其 onNewIntent() 方法将意图路由到现有实例,而不是创建新实例。

好吧,如果我理解正确的话,singleTask活动只能是它们任务的根源,因为它们是这样创建的,并且活动从不交换后堆栈中的位置。但是,这样的活动在收到对其onNewIntent()方法的调用时会如何反应?

该页面上关于此问题的另一条评论:

作为另一个示例,Android 浏览器应用程序声明 Web 浏览器活动应始终在其自己的任务中打开 - 通过在元素中指定 singleTask 启动模式。这意味着如果您的应用程序发出打开 Android 浏览器的意图,它的活动不会与您的应用程序放在同一任务中。相反,要么为浏览器启动一个新任务,要么,如果浏览器已经在后台运行了一个任务,则该任务被提出来处理新的意图。

因此,该指南指出调用singleTask活动会以某种方式将其向前推进。但是,如果该活动不在其任务之上,这怎么可能是真的呢?活动是否已恢复,或者它只是接收到对其onNewIntent()方法的调用而不向用户显示?我真的不明白。

PS:一年多前已经问过一个几乎相同的问题,但没有给出正确的答案。因此,虽然从技术上讲我的问题是重复的,但我有一种重新提出的冲动,因为它确实值得一个清晰明确的答案。

4

1 回答 1

3

我会尽力回答你的问题。

首先,

堆栈中的 Activity 永远不会重新排列,只会从堆栈中压入和弹出——当当前 Activity 启动时将其压入堆栈,并在用户使用“后退”按钮离开时弹出。

这实际上是错误的。通常,堆栈中的活动永远不会重新排列,但您可以Activity使用Intent.FLAG_ACTIVITY_REORDER_TO_FRONT. 例如,您的活动堆栈如下所示: A->B->C->D 其中A是根活动(在堆栈的底部),并且D是在前台(正在显示)中的最顶部活动。如果D现在这样做:

Intent intent = new Intent(this, B.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);

这会将现有的活动实例移动B到任务的前面,这样它就不会显示在屏幕上。活动堆栈现在看起来像这样:A->C->D->B。

接下来你问这个:

系统创建一个新任务并在新任务的根部实例化活动。但是,如果活动的实例已经存在于单独的任务中,系统会通过调用其方法将意图路由到现有实例onNewIntent(),而不是创建新实例。

好吧,如果我理解正确的话,singleTask活动只能是它们任务的根源,因为它们是这样创建的,并且活动从不交换后堆栈中的位置。但是这样的活动在收到对其onNewIntent()方法的调用时会如何反应呢?

通常,singleTask活动是其任务的根。如果已经有一个singleTask活动在其中的现有任务,并且您使用 启动这样的活动startActivity(),那么该任务将被提出(以便它显示在屏幕上)并将onNewIntent()在该活动的现有实例上调用。但是,如果该活动在其任务中启动了其他活动,则所有这些其他活动都将在该活动的现有实例上调用之前singleTask完成(即:该任务被剥离回其根Activity)。onNewIntent()singleTask

在某些情况下,singleTask活动不是其任务的根源,然后所有的赌注都被取消(即:行为没有记录在案)。如果该活动与应用程序中已在任务中处于活动状态的其他活动singleTask相同,则可能会发生这种情况。taskAffinity在这种情况下,Android 会忽略singleTask启动模式并将 Activity 视为具有standard启动模式。

于 2017-08-04T12:42:28.547 回答