怎样在按下主页按钮时清除活动历史堆栈?

7
我正在编写一个带有两种“模式”的应用程序;一种是查看模式,另一种是编辑模式。该应用程序公开两个主要/启动器活动(称为AD),它们各自都有自己的活动链(BCEF)。这两个入口点活动 AD 将在主屏幕上显示两个具有不同标签的图标,并且这两个链永远不会交叉,即一旦您以视图模式从活动 A 开始运行应用程序,则您可以来回穿梭的唯一路线是 ABC,如果您以编辑模式从活动 D 开始启动应用程序,则唯一可用的活动链是 DEF
现在,我的问题是,如果我以查看模式(活动链 ABC)启动应用程序,并从该链中的任何活动按下 Home 按钮,我将返回到主屏幕(当然),但如果我随后以编辑模式(活动链 DEF)重新启动应用程序,则我会回到按下 Home 按钮时所在的活动(也就是错误链中的一个活动),而不是预期的编辑模式入口点;活动 D我该怎么解决这个问题? 我尝试了在涉及的活动的 AndroidManifest.xml 中使用各种组合的 android:noHistory、android:clearTaskOnLaunch 和其他属性,但它们似乎只影响特定的活动,而不是整个链。
我希望在按下 Home 按钮时从历史堆栈中删除整个活动链(ABCDEF),但仍然保持该链在内部完整(我希望能够从活动 B 按下返回按钮并到达活动 A)。

1
你应该关注这个:https://dev59.com/5XA75IYBdhLWcg3wGlAa - himanshu
1
@dbm:你是在寻找这个吗?http://nisha113a5.blogspot.com/?? 请回复。 - Pratik Bhat
嗨@himanshu!是的,那个问题可能也会让我得出一个可行的结论。谢谢你的提示! - dbm
嗨@android_hungry!那个解决方案可能有效。但我不确定是否会选择它作为我的主要实现。对我来说,它感觉有点像“黑暗巫术”,在某些设备上肯定行不通。这是我不能采取的捷径。 - dbm
@dbm: 是的,你说得对,我碰巧在同一天看到了那篇帖子,就在我阅读到你的问题时。 - Pratik Bhat
3个回答

4
听起来你需要在主页活动中使用Intent.FLAG_ACTIVITY_CLEAR_TOP标志,但是当然你不能在AndroidManifest.xml文件中添加这些标志。也许你应该有一个单一的入口点,然后启动正确的Activity - 你可以使用activity-alias来让用户看起来像两个入口点。
例如 - 你在清单文件中定义活动:
   <activity-alias
        android:label="@string/edit_app_name"
        android:name="launch_edit"
        android:targetActivity=".activities.LaunchActivity">
        <meta-data android:name="launch_type" android:resource="@string/launch_edit" />
    </activity-alias>
    <activity-alias
        android:label="@string/view_app_name"
        android:name="launch_view"
        android:targetActivity=".activities.LaunchActivity">
        <meta-data android:name="launch_type" android:resource="@string/launch_view" />
    </activity-alias>

然后在您的LaunchActivity中有:

ActivityInfo activityInfo = getPackageManager().getPackageInfo( this.getComponentName(), PackageManager.GET_ACTIVITIES|PackageManager.GET_META_DATA);
int launchTypeResource = activityInfo.metaData.getInt("launch_type");
String launchType = context.getString(launchTypeResource);
if(launchType == null) {
   // handle error
   throw new Exception();
}
Intent newIntent;
if(launchType.equals(context.getString(R.string.launch_view)) {
    newIntent = createIntent(ViewActivity.class);
} else if(launchType.equals(context.getString(R.string.launch_edit)) {
    newIntent = createIntent(EditActivity.class);
}
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(newIntent);

嗨@Martin!我稍微修改了你的代码片段,以实际获取与“activity-alias”相关联的元数据。结果发现它并不是通过调用“Intent”发送的,而是从“ActivityInfo”数据结构中读取的。 - dbm
1
非常好的答案!考虑到您所付出的努力以及您的回答是第一个(正确且基本可行),我给您打了个勾 :-) - dbm
@Martyn你能否编辑你的答案以包含正确的数据读取? - Ovidiu Latcu
@OvidiuLatcu,我现在已经重新建议了我的修复方案。不幸的是,似乎我还没有编辑其他人的问题/答案的权利,因此除了等待Martyn的审核外,我无法做更多事情。 - dbm
1
抱歉 - 我在度假! :D 已经更正了代码 - 感谢您指出。 - Martyn

4
请在按下主页按钮时使用以下方法:
Intent intent=new Intent(this, HomeClass.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

我认为这实际上是解决我的问题最简单的方法。然而,我将使用另一种实现方式,使得这个解决方案这次不适用于我的应用程序。不过,通过你的回答,我确实学到了一些东西,对此我表示感谢。 - dbm

1
你可以考虑为每个链路只使用一个Activity(即只有AD)。
然后将ABC以及DEF的内容实现为片段,并在前进和后退时仅更改Activity上显示的片段。
结合使用android:noHistory,你应该可以获得所需的效果 - 尽管这需要一些重写,并且如果你计划针对低于Honeycomb版本的目标版本,则需要将兼容性包含到你的项目中。

这实际上是一个非常优雅的片段使用,由于我的应用程序已经由片段构建起来,所以甚至不需要进行大量重写。尽管我认为接受@Martyn的答案是公平的事情,但我认为这是我最终会选择的架构选择。感谢这个伟大的想法! - dbm

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