繁体   English   中英

如果已经在backstack中作为root,Android活动没有启动?

[英]Android activity not started if already in the backstack as the root?

我有一个包含3个活动的示例应用程序:Main,A和B.它们都没有任何launchMode。

现在我这样做:

  1. 打开应用程序,显示主要活动
  2. 使用后退按钮离开应用程序,以便没有活动正在运行
  3. 接收开始新活动的广播A(new_task标志)
  4. 通过单击活动A中的按钮打开活动B(无标记)
  5. 接收开始新活动的广播A(new_task标志)
  6. 新活动A 未启动 (如果我回去,仍然是之前的活动A)

在步骤#6,应该呈现活动A但不是。

如果我尝试呈现活动C(在#5中),则按预期显示。

如果在#2中我通过homebutton离开应用程序,一切都按预期工作。

这怎么可能? 我怎样才能确保始终展示活动? 我可以使用FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP ,但我想维护后台堆栈。

更新 - 来源:您可以查看源代码 ,但我使用的是Xamarin(基本上是用C#编写的原生Android,非常类似于Java)。 这是内置清单的内容(删除了Xamarin的东西):

<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:compileSdkVersion="28" android:compileSdkVersionCodename="9" package="com.companyname.StartTest" platformBuildVersionCode="28" platformBuildVersionName="9">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <application android:allowBackup="true" android:debuggable="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:name="android.app.Application" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
        <activity android:label="A" android:name="A"/>
        <activity android:label="B" android:name="B"/>
        <activity android:label="@string/app_name" android:name="MainActivity" android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <receiver android:name="Receiver"/>
    </application>
</manifest>

好吧,让我们按照操作顺序来看一下。

  1. 打开应用程序,显示主要活动

    靠背的状态: Main Activity (root)

  2. 使用后退按钮离开应用程序,以便没有活动正在运行

    靠背的状态: <No activity present as back was pressed>

  3. 接收开始新活动的广播A(new_task标志)

    Backstack的状态: ActivityA (root)

  4. 通过单击活动A中的按钮打开活动B(无标记)

    Backstack的状态: ActivityA (root) -> ActivityB (top)

  5. 接收开始新活动的广播A(new_task标志)

    Backstack的状态: ActivityA (root) -> ActivityB (top)

    此处Actvitity A未启动,因为它是使用意图标志'FLAG_ACTIVITY_NEW_TASK'启动的,其中包含以下文档:

使用此标志时,如果任务已在您正在启动的活动上运行,则不会启动新活动; 相反,当前任务将简单地以最后一个状态被带到屏幕的前面。

  1. 新活动A未启动(如果我回去,仍然是之前的活动A)

在步骤#6,应该呈现活动A但不是。

因此当前任务看起来像ActivityA (root) -> ActivityB(top)ActivityA已经存在于任务中,因此整个任务只是被带到前面 ,这意味着ActivityB仍然处于任务的最前面。

如果我尝试呈现活动C(在#5中),则按预期显示。

ActivityC是一项新任务,不在任务中,因此它是为您创建的。

如果在#2中我通过homebutton离开应用程序,一切都按预期工作。

关于homebutton press的事情是MainActivity在这种情况下没有被破坏,只是被推到了后台。

所以在#2之后,你的backstack的状态看起来仍然像MainActivity实例一样:

Main Activity (root)

现在,在#5之前,backstack看起来像这样:

Main Activity (root) -> ActivityA -> ActivityB (top)

在#5之后,你的靠背堆看起来像这样:

Main Activity (root) -> ActivityA -> ActivityB -> ActivityA (top)

我认为这样做的原因似乎是默认情况下使用intent标志启动MainActivity的方式:

FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

这也会触发任务重新创建,因此它可以控制使用新任务标志创建的新活动(与父应用程序具有相同的关联性)以及如何将此类活动移动到其任务。

您可以在此处找到更多相关信息

我怎样才能确保始终展示活动? 我可以使用FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP,但我想维护后台堆栈。

由于这是一个堆栈数据结构 ,因此您无法对活动进行重新排序,但是您可以通过添加标志来解决此问题: FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK 创建ActivityA的接收器中的FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK将确保为活动创建新的实例/任务,而不管它是否已存在。 (不是推荐的解决方案 - 但有效)

但是,如果要维护ActivityA的相同实例,则必须在清单中的活动中添加taskAffinity参数。

<activity android:name=".ActivityB" android:taskAffinity="com.example.pendingintent"></activity>
<activity android:name=".ActivityA" android:taskAffinity="com.example.abctest" />

然后使用new_task标志启动您的活动A和B.

是一个很棒的幻灯片,解释了taskAffinity及其如何影响活动的创建。

更新选项3:这应该将活动置于顶部。

intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);

option1:启动活动A时设置FLAG_ACTIVITY_REORDER_TO_FRONT。这会将活动A带到堆栈顶部。

activityAIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

选项2:通过Android文档,只有“标准”启动模式会创建活动的多个实例。

参见下表。

本文档介绍了每种模式的用法: https//developer.android.com/guide/topics/manifest/activity-element.html#lmode

如果您每次都想要新的实例,请将标准launchMode添加到您的活动A.

android:launchMode="standard"

在此输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM