我有一个包含3个活动的示例应用程序:Main,A和B。它们都没有任何launchMode。
现在我这样做:
在步骤#6中,应该显示活动A,但不显示。
如果我尝试呈现活动C(在#5中),则会按预期显示。
如果在#2中,我改用homebutton离开应用程序,则一切正常。
这怎么可能?以及如何确保始终显示活动?我可以使用FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP
,但我想维护后台程序。
更新-来源: 您可以看一下source,但我使用的是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>
答案 0 :(得分:1)
好的,让我们按照操作顺序来看看。
打开应用,显示主要活动
后退状态:Main Activity (root)
使用“后退”按钮离开应用程序,这样就不会有活动在运行
后退状态:<No activity present as back was pressed>
接收开始新活动A(new_task标志)的广播
后退状态:ActivityA (root)
通过单击活动A中的按钮打开活动B(无标志)
后退状态:ActivityA (root) -> ActivityB (top)
接收开始新活动A(new_task标志)的广播
后退状态:ActivityA (root) -> ActivityB (top)
此处未启动Actvitity A,因为它是用意图标记'FLAG_ACTIVITY_NEW_TASK'启动的,该意图标记具有以下文档:
使用此标志时,如果活动的任务已经在运行 您现在开始,那么新的活动将不会开始; 而是将当前任务简单地带到 屏幕上显示的是最后一次进入的状态。
在步骤#6中,应该显示活动A,但不显示。
所以当前任务看起来像这样
ActivityA (root) -> ActivityB(top)
,ActivityA
已经存在于任务中,因此任务 整体只是放在最前面,这意味着ActivityB
是 仍然在任务的顶部。
如果我尝试展示活动C(在#5中),则会按预期显示。
ActivityC
是任务中没有的新活动,因此它 为您创建。
如果在#2中,我改为通过Homebutton离开该应用程序,则一切正常。
按下homebutton的事情是MainActivity在这种情况下不会被破坏,只是被推送到后台。
因此,在#2之后,您的backstack状态仍然看起来像以MainActivity实例为根:
Main Activity (root)
现在,在#5之前,后堆栈应如下所示:
Main Activity (root) -> ActivityA -> ActivityB (top)
#5之后,您的堆栈看起来像这样:
Main Activity (root) -> ActivityA -> ActivityB -> ActivityA (top)
我相信,这似乎是由于MainActivity
默认情况下使用intent标志启动的方式:
FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
这还会触发任务重定,因此它可以控制使用新任务标记(与父应用程序具有相同的亲和力)创建的新活动,以及如何将此类活动移至其任务。
您可以找到有关此here
的更多信息我如何确保始终显示活动?我可以使用FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP,但我想维护后退堆栈。
由于这是堆栈数据结构,因此您无法重新排列活动,但是可以通过在创建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
Here是一张出色的幻灯片,解释了taskAffinity及其对活动创建的影响。
答案 1 :(得分:0)
更新选项3:。这应将“活动”置于顶部。
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
选项1 :在启动活动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
如果每次都需要新的实例,则向活动A添加标准的launchMode。
android:launchMode="standard"