为什么行为不同?- android:launchMode="singleTask",android:taskAffinity=""和Intent.FLAG_ACTIVITY_NEW_TASK

6
我有四个活动 - A,B,C,D。
我是按照A-B-C-D-B的方式调用这四个活动。(指定方式) 我有三种情况。 第一种: 我只在B Activity中定义了android:launchMode="singleTask"。并且我通过上述指定的方式使用Intent来调用所有活动。
现在首先调用A-B-C-D,BackStack Task 1 : A-B-C-D,
现在我再次调用B,则BackStack Task 1 : A-B。此处C和D活动被销毁。 第二种: 我在B Activity中定义了android:launchMode="singleTask"android:taskAffinity=""。并且我通过上述指定的方式使用Intent来调用所有活动。
现在首先调用A-B-C-D,BackStack Task 1 : A
                                  Task 2 : B-C-D

现在我再次调用B,然后返回栈任务1:A

                                Task 2 : B ,Here C and D Activities are destroyed.

第三步:我在B Activity中定义了Intent.FLAG_ACTIVITY_NEW_TASKandroid:taskAffinity="",并以上述方式通过Intent调用所有活动。

现在首先调用A-B-C-D,BackStack Task 1 : A

                                  Task 2 : B-C-D

现在我再次调用B,然后返回栈任务1:A


                                Task 2 : B-C-D , Here **Can't call B again**

这里提到FLAG_ACTIVITY_NEW_TASK与"singleTask"有相同的行为:https://developer.android.com/guide/components/activities/tasks-and-back-stack.html

那么哪些是正确的情境呢?我是理解得对还是误解了什么?


你在使用 singleTask 启动模式的活动中,是否使用过 onNewIntent() 方法? - mrid
不,我没有用过它。它的语法会是什么?我的意思是onNewIntent()的语法。 - zephyr
但是,我在活动之间没有传递任何值,所以我一定要重写onNewIntent()方法吗? - zephyr
你从哪里启动这些活动?是 A 启动 B,然后 B 启动 CC 启动 D,最后 D 又启动 B 吗? - David Wasser
@mrid,onNewIntent()的使用与此问题完全无关。 - David Wasser
显示剩余6条评论
2个回答

8
我已经按照您的描述重现了此行为。
第一种情况基本上没有文档说明,因为一个singleTask Activity 应该始终是任务的根。因为Android在确定如何和在哪里启动Activity时使用taskAffinity,所以你的singleTask Activity正在现有任务中启动,但不是作为根Activity。这使得行为与文档中记录的行为不同。当你从D启动B时,Android需要通过调用onNewIntent()将Intent传递给B,在C和D位于B之上时,它无法这样做。所以Android完成C和D,然后在B上调用onNewIntent()。
第二种情况表明现在有两个任务,因为singleTask Activity作为根Activity被启动到一个新任务中。同样,当D启动B时,Android需要通过调用onNewIntent()将Intent传递给B,如果C和D挡住了路,它就无法这样做。所以Android完成C和D,然后在onNewIntent()中将Intent传递给B。
第三种情况展示了FLAG_ACTIVITY_NEW_TASK的使用。当A使用FLAG_ACTIVITY_NEW_TASK启动B时,Android会查找具有B作为根Activity的现有任务。由于它找不到,它会将B作为根Activity启动到一个新任务中。当D使用FLAG_ACTIVITY_NEW_TASK启动B时,Android会查找具有B作为根Activity的任务,并且如果找到了一个任务,它会将该任务带到前台,但不会将Intent传递给onNewIntent()。这只是将现有任务带到后台时保持其状态的一种方法。这就是你看到的行为。这种行为也有文档(有点),但由于所有这些情况之间非常复杂的相互依赖关系,所有可能的情况都没有明确记录。有时候你需要通过实证观察来发现这是如何工作的,而不是通过阅读文档。
谢谢您的挑战。

3
David Wasser,感谢您详细的回答。非常有用。但我有一个问题。如您所解释的第三种情况,>当D使用FLAG_ACTIVITY_NEW_TASK启动B时,Android会查找具有B作为根Activity的任务,如果找到,则将该任务带到前台,但不会将Intent传递给onNewIntent()。>但在我的情况下,在我从D再次调用B时,似乎无法再次调用。它没有切换到Activity B。 它卡在Activity D上。为什么会这样? - zephyr
3
在第三种情况下,Android 将任务带到前台。任务以 B 为根,但是 D 是最上层的 Activity,因此它正在显示。如果你真的想把 B 置于顶部(以便它显示),你可以使用 Intent.FLAG_ACTIVITY_REORDER_TO_FRONT(这将把 B 放在 D 的上方),或者使用 Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP,它将结束 DC 并显示 B 的现有实例,或者只需使用 Intent.FLAG_ACTIVITY_CLEAR_TOP,将结束 DCB,然后启动一个新的 B 实例。 - David Wasser
2
因此,总的来说,Intent.FLAG_ACTIVITY_NEW_TASK(只有单个属性)不会作为“singleTask”起作用。非常感谢。现在它如你所描述的那样正常工作 :-) - zephyr

0
作为上面答案的补充,现在我正在使用API 29的pixel 2,场景1和2的结果仍然相同,但在场景3中,会将B的一个新实例添加到任务栈中,而不仅仅是将任务带到前台。
不幸的是,这种行为仍然没有得到很好的记录。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接