源代码可以在这里找到: https://github.com/novemberox/NavigationTest它修改了这个样本的版本: http://developer.android.com/training/implementing-navigation/ancestral.html
我有三项活动:
-
Main Activity
只是主入口应用 -
Category Activity
它是详细活动父 -
Detail Activity
Main Activity
有按钮,打开Category Activity
和Detail Activity
。 Category Activty
只有一个按钮,打开Detail Activity
。 最后Detail Activity
,显示一些文字,并拥有高达按钮,模拟点击动作条了。
我的“点击”路径是:
- 开放的主要活动
- 打开详细活动
- 点击“向上按钮”
- 分类Activty应该出现
- 回来点击移动我们主要活动与状态恢复
这是流程是将期待它的工作只是罚款果冻豆每前的Android(在Galaxy Nexus的4.1.1和4.2模拟器谷歌EXP包测试)。 它的工作原理即使在ICS。 我的样品,我在开始时所指出使用支持lib和类,如NavUtils和TaskStackBuilder,等等。
在JB当我点击“向上按钮”它可以追溯到主要活动与国家正确地恢复。 我看着支持库的源代码,我看到NavUtils.navigateUpTo
方法调用像本地JB代码Activity#navigateUpTo
。 我都尝试NavUtils#navigateUpTo()
和NavUtils.navigateUpFromSameTask()
使用相同的不满意的结果。
你有一些建议,怎样做才能有这个漂亮的流程?
首先第一件事情,如果你的目标设备高达17 API(安卓4.2),设置targetSdkVersion
在您的清单17。 这对老设备不破的支持,它只是使事情正常工作的新设备。 当然,这并不解决您的问题 - 这是一个好的做。
你应该怎么使用?
我假设你在基础代码关公祠导航例子此页 。 你已经使用了第二个例子:
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
有:
upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(upIntent);
finish();
为什么它在ICS和先前的工作?
一般情况下,支持库正试图接近在以后的API中引入的行为。 在的情况下NavUtils
,支持库正试图接近在API 16(又名安卓4.1)推出的bahavior。 对于-API前16米的平台, NavUtils用途:
@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(意向upIntent)
从该活动到由upIntent指定的活动导航,整理过程中的这活性。 如果upIntent表示活动的任务的历史记录已经存在,这个活动和所有其他在历史堆栈中指定的活动之前将完成。
如果指定的活动不会在历史堆栈中出现,直至达到任务的根系活力 ,导致“应用程序内的家”的行为,这将完成此任务中每个活动 。 当一个活动可通过不经过规范父活动的路径来达到这可以是在具有复杂的导航层次结构的应用是有用的。
从这一点,目前还不清楚它是否会推出在指定的活动upIntent
如果不是在后面堆栈。 阅读源代码并不有助于澄清事情无论是。 然而,从您的应用程序显示的行为来看,似乎它并不试图启动upIntent
活动。
无论哪个实施是正确的还是错误的,最终的结果是你想要的FLAG_ACTIVITY_CLEAR_TOP
行为,而不是原生API 16的行为。 不幸的是,这意味着你将不得不重复支持库逼近。
哪个是对的?
免责声明:我不是为谷歌工作,所以这是我最好的猜测。
我的猜测是,API 16+的行为是预期的行为; 它是一个内置的实现可以访问Android的内部,可以做的事情是不可能通过API。 预API 16,我不认为这是可能的放松以这种方式比使用意向的标志以外的堆栈中。 因此, FLAG_ACTIVITY_CLEAR_TOP
标志是提供给预API 16个平台上的API 16行为最接近 。
不幸的是,结果是本机实现和支持库的实现之间存在的违反最小惊讶的原则,在方案中。 这使我不知道这是一个意料之外的使用的API。 也就是说,我不知道Android的期待,你遍历完整的导航路径的活动,而不是直接跳转到它。
以防万一
只是为了避免一个可能的误解,也可能有人会想到shouldUpRecreateTask
神奇地确定父是不是在后退堆栈和经过合成的一切,你使用的过程TaskStackBuilder
。
然而, shouldUpRecreateTask
基本决定,如果你的活动是由您的应用程序(在这种情况下,它会返回直接启动false
),或者如果它是从另一个应用程序启动(在这种情况下,它返回true
)。 从本书中 ,支持库检查目的的“行动”是不是ACTION_MAIN
(我不完全明白),而在API 16个平台上,进行基于任务的亲和力此检查。 不过,在此应用程序的情况下,工作的事情出来shouldUpRecreateTask
返回false。
阅读@ cyfur01的回答后,我想出了非常简单的解决方案,修复行为。
在您的活动(在某些BaseActivity把它修好了所有子类或理想)覆盖此方法并预期它应该工作:
@Override
public boolean navigateUpTo(Intent upIntent) {
boolean result = super.navigateUpTo(upIntent);
if (!result) {
TaskStackBuilder.create(this)
.addNextIntentWithParentStack(upIntent)
.startActivities();
}
return result;
}
它让所有的工作到Android的实施,然后就检查返回值navigateUpTo(upIntent)
这是false
,当指定活动的实例无法找到,这项活动是简单的正常结束 。 这是当我们要建立和手动启动父活动正是如此。 另外请注意,我们不必调用finish()
在这里,因为它是由超级方法调用。