[英]Android activity not started if already in the backstack as the root?
我有一个包含3个活动的示例应用程序:Main,A和B.它们都没有任何launchMode。
现在我这样做:
在步骤#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>
好吧,让我们按照操作顺序来看一下。
打开应用程序,显示主要活动
靠背的状态: Main Activity (root)
使用后退按钮离开应用程序,以便没有活动正在运行
靠背的状态: <No activity present as back was pressed>
接收开始新活动的广播A(new_task标志)
Backstack的状态: ActivityA (root)
通过单击活动A中的按钮打开活动B(无标记)
Backstack的状态: ActivityA (root) -> ActivityB (top)
接收开始新活动的广播A(new_task标志)
Backstack的状态: ActivityA (root) -> ActivityB (top)
此处Actvitity A未启动,因为它是使用意图标志'FLAG_ACTIVITY_NEW_TASK'启动的,其中包含以下文档:
使用此标志时,如果任务已在您正在启动的活动上运行,则不会启动新活动; 相反,当前任务将简单地以最后一个状态被带到屏幕的前面。
在步骤#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.