如何在Navigation Components的addOnDestinationChangedListener中获取回退栈数量
解决方法
方案1:反射获取完整回退栈
直接通过反射读取NavController的内部回退栈字段即可拿到准确数据,不会有竞态误差,代码示例如下:
// 给NavController写扩展方法获取实际目的地回退栈数量 fun NavController.getActualBackStackCount(): Int { return runCatching { val backStackField = NavController::class.java.getDeclaredField("backStack") backStackField.isAccessible = true val backStack = backStackField.get(this) as Deque<*> // 过滤掉导航图自身的栈条目,仅统计Fragment/Activity目的地的数量 backStack.count { entry -> entry is NavBackStackEntry && entry.destination !is NavGraph } }.getOrDefault(0) }
在addOnDestinationChangedListener里直接调用这个扩展方法就能拿到实时准确的回退栈数量,完全符合你的使用需求。如果后续Navigation库版本升级内部字段名变更,只要同步修改反射的字段名即可。
方案2:无反射的规范实现(更推荐)
你的核心需求是区分页面场景控制底部导航显隐,完全不需要强依赖回退栈计数。可以给导航图里的每个目的地添加自定义布尔参数showBottomNav,不同跳转场景传入对应的参数值即可:
- 首先在导航图XML中给目的地配置参数:
<fragment android:id="@+id/target_fragment" android:name="com.xxx.TargetFragment"> <argument android:name="showBottomNav" android:defaultValue="false" app:argType="boolean" /> </fragment>
- 不同场景跳转时传入对应参数:
- 底部导航一级页面跳转时传
true - 深层页面跳转、deeplink跳转时传
false
- 在
addOnDestinationChangedListener中直接读取参数控制显隐:
navController.addOnDestinationChangedListener { _, _, args -> val isShow = args?.getBoolean("showBottomNav") ?: false bottomNavigationView.visibility = if (isShow) View.VISIBLE else View.GONE }
这个方案兼容性更强,不需要适配Navigation版本变更,也符合官方设计规范。
内容的提问来源于stack exchange,提问作者David Corrado
相关产品推荐
相关产品推荐

