Navigation#popBackStack收获
findNavController().navigateUp()
Navigation管理的Fragment中可以通过navigateUp返回上一页,这里可以先从navigateUp入手,看下其源码:
public boolean navigateUp() {
if (getDestinationCountOnBackStack() == 1) {
// emmm,略去一大坨
return false;
} else {
return popBackStack();
}
}
从getDestinationCountOnBackStack的方法名以及if语句的判断条件来看当前任务栈中只有一个fragment时才走这里,猜测是结束当前Activity的操作这里不深入探究。
看下else内的逻辑,调用了popBackStack()方法,继续深究吧 ->
public boolean popBackStack() {
if (mBackStack.isEmpty()) {
// Nothing to pop if the back stack is empty
return false;
}
// Pop just the current destination off the stack
return popBackStack(getCurrentDestination().getId(), true);
}
这个方法也很简单,当任务栈不为空时直接调用popBackStack的两个参数重载方法,并且第一个参数我们能够看懂传递的是当前fragment目的地的id。
继续深究->
/**
Attempts to pop the controller's back stack back to a specific destination.
Params: destinationId – The topmost destination to retain
inclusive – Whether the given destination should also be popped.
Returns: true if the stack was popped at least once and the user has been navigated to another
destination, false otherwise
* */
public boolean popBackStack(@IdRes int destinationId, boolean inclusive) {
boolean popped = popBackStackInternal(destinationId, inclusive);
// Only return true if the pop succeeded and we've dispatched
// the change to a new destination
return popped && dispatchOnDestinationChanged();
}
妹的不翻译了,解释的够清楚了。注意下inclusive这个参数很有意思,借助这个参数我们能够实现若干个页面弹出栈的功能。假如有页面FragmentA -> FragmentB -> FragmentC ->FragmentD 目前停留在FragmentD页面:
1、想要关闭当前FragmentD页面
findNavController().apply {
popBackStack(currentDestination!!.id,true)
}
哈哈哈哈,这不就是navigateUp 站内非空走的逻辑嘛~
2、想要从当前FragmentD跳转到FragmentB,且FragmentC、FragmentD 出站
//做法1
popBackStack(destinationBId, false)
//做法2
popBackStack(destinationCId, true)
有两种做法:
第一种做法是直接跳到FragmentB,inclusive 设置为false 不让FragmentB出栈即可。FragmentC、FragmentD自动出站的。
第二种做法是直接跳到FragmentC,inclusive 设置为true 让FragmentC出栈即可,这样就自动把FragmentB放到栈顶了,FragmentD自动出站的。