在 Android 导航架构中,如何检查当前片段是否是最后一个片段?

In Android Navigation Architecture, how can I check if current Fragment is the last one?

我需要显示自定义 AlertDialog,但只有在调用 NavController.navigateUp() 后没有更多片段时才会显示。我当前的代码做了类似的事情,但是有一个错误:

override fun onBackPressed() {

    if (navController.navigateUp()) {
        return
    }

    showQuitDialog()
}

这有点管用,但是如果我取消 AlertDialog 并且不退出应用程序,navController 已经导航到 NavGraph root,这不是其中的片段我在AlertDialog出现的时候。因此,如果我尝试使用该片段中的任何导航操作,我会收到错误消息:

java.lang.IllegalArgumentException: navigation destination com.example.test/actionNavigateToNextFragment is unknown to this NavController

如果我可以访问 NavController 中的 mBackStack 字段,但它是 package private,并且我无法在当前项目中使用反射,则可以解决此问题。但如果它是 public,我会按以下方式使用它:

override fun onBackPressed() {

    // 2 because first one is NavGraph, second one is last fragment on the stack
    if(navController.mBackStack.size > 2) { 
        navController.navigateUp()
        return
    }

    showQuitDialog()
}

有没有不用反射的方法?

您可以将起始目的地的ID与当前目的地的ID进行比较。类似于:

override fun onBackPressed() = when {
    navController.graph.startDestination == navController.currentDestination?.id -> showQuitDialog()
    else -> super.onBackPressed()
}

希望对您有所帮助。

针对任何目的地尝试此操作(您可以在导航图中找到您的目的地 ID):

private fun isDesiredDestination(): Boolean {
    return with(navController) {
        currentDestination == graph[R.id.yourDestinationId]
    }
}

如果你想要这是一个按钮,可以这么说,你可以拥有这个

yourbutton.setOnClickListener {
            val currentFragment = navController.currentDestination?.id
           when (navController.graph.startDestination == currentFragment) {
                true ->  { //Go here}
                 // Go to the app home
                else -> onBackPressed()
            }
        }

比较目标 ID 可能不是最佳解决方案,因为您可能有多个屏幕具有相同的 ID,但后台堆栈中的参数不同。

这是一个替代方案:

val isRootScreen = navController.previousBackStackEntry == null