JellyBean 上的向上导航损坏了?

2024-03-04

源代码可在此处获取:https://github.com/novemberox/NavigationTest https://github.com/novemberox/NavigationTest这是该示例的修改版本:http://developer.android.com/training/implementing-navigation/ancestral.html http://developer.android.com/training/implementing-navigation/ancestral.html

我有三项活动:

  • Main Activity只是应用程序的主要入口
  • Category Activity它是详细活动的父级
  • Detail Activity

Main Activity有打开按钮Category Activity and Detail Activity. Category Activty只有一个打开按钮Detail Activity。 最后Detail Activity显示一些文本并具有模拟单击 ActionBar 向上的向上按钮。

我的“点击”路径是:

  • 打开主要活动
  • 打开详细活动
  • 点击“向上按钮”
  • 应出现类别活动
  • 后退单击将我们移至主活动并恢复状态

这是我们所期待的流程,并且在 Jelly Bean 之前的所有 Android 上都运行得很好(在 Galaxy Nexus 4.1.1 和模拟器 4.2 Google exp pack 上进行了测试)。它甚至可以在 ICS 上运行。我正在使用支持库和 NavUtils 和 TaskStackBuilder 等类,就像我在开始时指出的示例中一样。

在 JB 上,当我单击“向上按钮”时,它会返回到主活动,并且状态已正确恢复。我查看了支持库的源代码,我看到了NavUtils.navigateUpTo方法调用本机 JB 代码,例如Activity#navigateUpTo。我都尝试过NavUtils#navigateUpTo() and NavUtils.navigateUpFromSameTask()结果同样不令人满意。

你有什么建议可以做什么才能有这样好的流程吗?


首先,如果您的目标设备高达 API 17 (Android 4.2),请设置targetSdkVersion到您的清单中的 17。这不会破坏对旧设备的支持,它只会使新设备正常工作。当然,这并不能解决你的问题——这样做就好了。

你应该使用什么?

我假设您的代码基于祖先导航示例这一页 http://developer.android.com/training/implementing-navigation/ancestral.html。您已经使用了第二个示例:

Intent upIntent = new Intent(this, MyParentActivity.class);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
    // This activity is not part of the application's task, so create a new task
    // with a synthesized back stack.
    TaskStackBuilder.from(this)
        .addNextIntent(new Intent(this, MyGreatGrandParentActivity.class))
        .addNextIntent(new Intent(this, MyGrandParentActivity.class))
        .addNextIntent(upIntent)
        .startActivities();
    finish();
 } else {
     // This activity is part of the application's task, so simply
     // navigate up to the hierarchical parent activity.
     NavUtils.navigateUpTo(this, upIntent);
 }

但是,对于您想要的行为,您需要替换NavUtils.navigateUpTo with:

upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(upIntent);
finish();

为什么它适用于 ICS 及更早版本?

总的来说,支持库正在尝试近似后续 API 中引入的行为。如果是NavUtils,支持库正在尝试近似 API 16(又名 Android 4.1)中引入的行为。对于 API 16 之前的平台,NavUtils https://android.googlesource.com/platform/frameworks/support/+/57ff0548ba991652576d81adaaa8baf4c028de39/v4/java/android/support/v4/app/NavUtils.java uses:

@Override
public void navigateUpTo(Activity activity, Intent upIntent) {
    upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    activity.startActivity(upIntent);
    activity.finish();
}

这会在返回堆栈中查找指定的活动实例upInent。如果它找到一个,它会清除所有内容并恢复它。否则它只会启动该活动。

在 API 16+ 更高版本的平台上,支持库将事情交给本机调用ActivityAPI。根据文档:

公共布尔navigateUpTo(Intent upIntent)

从此 Activity 导航到 upIntent 指定的 Activity,并在流程中完成该 Activity。如果 upIntent 指示的活动已存在于任务的历史记录中,则该活动以及历史堆栈中指示的活动之前的所有其他活动都将完成。

如果指定的活动没有出现在历史堆栈中,这将完成此任务中的每个活动,直到到达任务的根活动,导致“应用内主页”行为。当可以通过不经过规范父活动的路径到达活动时,这在具有复杂导航层次结构的应用程序中非常有用。

由此看来,目前还不清楚它是否会启动中指定的活动。upIntent如果它不在返回堆栈中。阅读源代码 https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/Activity.java#L4965也无助于澄清事情。但是,从您的应用程序显示的行为来看,它似乎does not尝试启动upIntent活动。

不管哪种实现是对还是错,最终的结果都是你想要的FLAG_ACTIVITY_CLEAR_TOP行为,而不是本机 API 16 行为。不幸的是,这意味着您必须复制支持库近似值。

哪个是对的?

免责声明:我不在 Google 工作,所以这是我的最佳猜测。

我的猜测是 API 16+ 行为是预期的行为;它是一个内置实现,可以访问 Android 内部结构,并且可以完成通过 API 无法完成的操作。在 API 16 之前,我认为除了使用意图标志之外不可能以这种方式展开返回堆栈。就这样FLAG_ACTIVITY_CLEAR_TOP标志是最接近的近似值API 16 之前的平台可用的 API 16 行为。

不幸的是,结果是本机实现和支持库实现之间违反了最小惊讶原则 http://en.wikipedia.org/wiki/Principle_of_least_astonishment在你的场景中。这让我怀疑这是否是 API 的意外使用。也就是说,我想知道 Android 是否希望您遍历活动的完整导航路径,而不是直接跳转到它。

万一

只是为了避免一种可能的误解,有人可能会期望shouldUpRecreateTask神奇地确定父级不在返回堆栈中,并使用以下命令完成为您合成所有内容的过程TaskStackBuilder.

然而,shouldUpRecreateTask基本上确定您的活动是否是由您的应用程序直接启动的(在这种情况下它返回false),或者如果它是从另一个应用程序启动的(在这种情况下它返回true). From ,支持库检查意图的“动作”是否不是ACTION_MAIN(我不完全理解这一点),而在 API 16 平台上,它根据任务关联性执行此检查。不过,就这个应用程序而言,事情的结果是shouldUpRecreateTask返回假。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JellyBean 上的向上导航损坏了? 的相关文章

随机推荐