首先,如果您的目标设备高达 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+ 更高版本的平台上,支持库将事情交给本机调用Activity
API。根据文档:
公共布尔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
返回假。