当使用 startActivityForResult 启动活动时,LaunchMode "singleTop" 会被忽略

Posted

技术标签:

【中文标题】当使用 startActivityForResult 启动活动时,LaunchMode "singleTop" 会被忽略【英文标题】:LaunchMode "singleTop" is ignored when activity is started with startActivityForResult 【发布时间】:2020-02-01 22:44:01 【问题描述】:

我使用startActivityForResult() 启动一个活动,并希望防止在活动堆栈顶部启动多个实例。所以我希望android:launchMode="singleTop" 能够完成它的工作,但由于某种原因,该标志被忽略了。

经过一些调查,我设法通过在意图中添加FLAG_ACTIVITY_REORDER_TO_FRONT 来仅启动一个实例,但如果有人能解释为什么“singleTop”在这种情况下不起作用,我将不胜感激。代码很简单。

// Activity class
Intent intent = new Intent(this, DetailsActivity.class);
// multiple instances can be launched without this line
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); 
startActivityForResult(intent, REQUEST_CODE_DETAILS);

// AndroidManifest.xml
<activity
    android:name=".DetailsActivity"
    android:launchMode="singleTop"/>

【问题讨论】:

【参考方案1】:

SingleTop 是如何工作的?

假设您有当前的活动堆栈,例如

A->B->C

现在从当前活动 C,如果你启动 A 活动,它是一个单一的Top,所以在这种情况下,系统将创建一个新的 A 实例并将该实例带到顶部。 (如果指定的活动不在顶部,则将创建新实例)

所以堆栈看起来像

A->B->C->A

现在,如果您再次尝试打开 A,那么在这种情况下,A 已经在顶部,因此将创建 NO 新实例。相反,A 将在 onNewIntent() 方法中接收回调

标志

FLAG_ACTIVITY_REORDER_TO_FRONT

它从堆栈的前端扫描到堆栈的后端,如果找到指定活动的实例,则将该活动带到前面。

所以在你的情况下,如果 DetailsActivity instacne 已经存在于系统中,那么这个标志会将 DetailsActivity 带到前面

【讨论】:

是的,这就是我所期望的,这就是它在通常的 startActivity() 中的工作方式。但是如果使用 startActivityForResult() 和 launchMode="singleTop" 启动活动 C,A->B->C 堆栈会变成 A->B->C->C 并且不会调用 onNewIntent()。【参考方案2】:

在这种情况下必须忽略标志FLAG_ACTIVITY_SINGLE_TOP,因为当您使用startActivityForResult() 启动Activity 时,您基本上是在说您要启动Activity 并让Activity 返回结果。

如果此Activity 的实例已存在于堆栈中(无论它在堆栈中的什么位置),则该实例尚未设置为将结果返回给您的Activity。该实例可能是使用startActivity() 启动的,在这种情况下,它根本没有设置为返回结果。它可能是使用另一个ActivitystartActivityForResult() 启动的,在这种情况下,它被设置为将结果返回给启动它的Activity,而不是你的Activity

这两件事:FLAG_ACTIVITY_SINGLE_TOPstartActivityForResult() 因此是冲突的。

【讨论】:

以上是关于当使用 startActivityForResult 启动活动时,LaunchMode "singleTop" 会被忽略的主要内容,如果未能解决你的问题,请参考以下文章

为啥当我解构属性时接收道具的组件不起作用,但是当我使用 props.key 时它起作用了?

当我们使用 JavaScript 隐藏/显示时清除下拉列表和/或文本框内容当它们被交替选择时

当 Model 超出使用范围时,实际会发生啥?

RHandsontable 不正确的输入转换,当使用格式时

当我们使用它时,线程本地是啥? [复制]

当我们有 OkHttp 时为啥要使用 Retrofit