首页 > 解决方案 > 检查导航图是否在 backstack 上

问题描述

我的导航图有一个auth包含 LoginFragment 和 SignUpFragment 的子图:

<navigation
    android:id="@+id/auth"
    app:startDestination="@id/loginFragment">
    <fragment
        android:id="@+id/signUpFragment"
        [...]
    <fragment
        android:id="@+id/loginFragment"
        [...]
    </fragment>
    [...]
</navigation>

我想检查这两个目的地中的任何一个当前是否在后台。但不是单独检查每个目的地,如下所示:

val currentDestId = navController.currentDestination?.id
if (currentDestId != R.id.loginFragment && currentDestId != R.id.signUpFragment) {
    navController.navigate(
        NavGraphDirections.actionGlobalLogin()
    )
}

我认为只检查身份验证图当前是否在后堆栈上会更干净。

我目前的方法如下:

val authBackStack = try {
    navController.getBackStackEntry(R.id.auth)
} catch (t: Throwable) {
    null
}
if (authBackStack == null) {
    navController.navigate(
        NavGraphDirections.actionGlobalLogin()
    )
}

这里的想法是,如果传递的目的地(或本例中的图形)当前不在后堆栈上,则getBackStackEntry抛出一个。IllegalStateException我们使用这个异常作为一个指标来确定我们的图当前是否在后栈中。

这是一种有效的方法还是会在某些情况下中断?或者也许有更好的方法来检查后堆栈是否包含某个子图的目的地?

标签: androidnavigationandroid-architecture-componentsandroid-architecture-navigation

解决方案


这是正确的方法,但您可以将其隐藏为扩展函数,如下所示:

fun NavController.isOnBackStack(@IdRes id: Int): Boolean = try { getBackStackEntry(id); true } catch(e: Throwable) { false }

这样你实际上得到了你想要的布尔值,同时隐藏了基于异常的控制流(这是由于 Jetpack Navigation 公开的 API 的要求)。


推荐阅读