当我试图从一个片段导航到另一个片段时,我遇到了新的Android导航架构组件的问题,我得到了这个奇怪的错误:

java.lang.IllegalArgumentException: navigation destination XXX
is unknown to this NavController

其他导航都很好,除了这个。

我使用Fragment的findNavController()函数来访问NavController。

任何帮助都将不胜感激。


当前回答

造成这个问题的原因可能有很多。 在我的情况下,我正在使用MVVM模型,我正在观察布尔导航 当布尔值为true时->导航 否则什么都不要做 这工作得很好,但这里有一个错误

当从目标片段按下返回按钮时,我遇到了同样的问题。问题是布尔对象,因为我忘记将布尔值更改为false,这造成了混乱。我刚刚在viewModel中创建了一个函数,将其值更改为false,并在findNavController()之后调用它

其他回答

试试

创建以下扩展函数(或普通函数):

UPDATED(不带反射,可读性更强)

import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.NavDirections
import androidx.navigation.fragment.DialogFragmentNavigator
import androidx.navigation.fragment.FragmentNavigator

fun Fragment.safeNavigateFromNavController(directions: NavDirections) {
    val navController = findNavController()
    when (val destination = navController.currentDestination) {
        is FragmentNavigator.Destination -> {
            if (javaClass.name == destination.className) {
                navController.navigate(directions)
            }
        }
        is DialogFragmentNavigator.Destination -> {
            if (javaClass.name == destination.className) {
                navController.navigate(directions)
            }
        }
    }
}

老了(沉思)

import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.NavDirections
import androidx.navigation.fragment.FragmentNavigator

inline fun <reified T : Fragment> NavController.safeNavigate(directions: NavDirections) {
    val destination = this.currentDestination as FragmentNavigator.Destination
    if (T::class.java.name == destination.className) {
        navigate(directions)
    }
}

然后像这样使用你的片段:

val direction = FragmentOneDirections.actionFragmentOneToFragmentTwo()
// new usage
safeNavigateFromNavController(direction)

// old usage
// findNavController().safeNavigate<FragmentOne>(action)

我的问题是

我有一个片段(FragmentOne),它指向另外两个片段(FragmentTwo和FragmentThree)。在一些低级设备中,用户按下重定向到FragmentTwo的按钮,但在用户按下重定向到FragmentThree的按钮几毫秒后。结果是:

致命异常:java.lang.IllegalArgumentException导航 action/destination action_fragmentOne_to_fragmentTwo找不到 来自当前目的地 类= FragmentThree

我的答案是:

我检查当前目的地是否属于当前片段。如果为真,则执行导航操作。

就这些!

如果你点击太快,它会导致null和崩溃。

我们可以使用RxBinding库来帮助这一点。你可以在点击发生之前添加节流和持续时间。

 RxView.clicks(view).throttleFirst(duration, TimeUnit.MILLISECONDS)
            .subscribe(__ -> {
            });

这些关于在Android上节流的文章可能会有所帮助。干杯!

答案在链接:https://stackoverflow.com/a/67614469/5151336

为导航器增加了安全导航的扩展功能。

正如在其他回答中提到的,此异常通常发生在用户

同时单击处理导航的多个视图 在处理导航的视图上多次单击。

使用计时器来禁用单击并不是处理此问题的合适方法。如果用户在计时器过期后还没有导航到目的地,应用程序无论如何都会崩溃,在许多情况下,导航不是执行的动作,快速点击是必要的。

在情况1中,android:splitMotionEvents=“false”在xml或setMotionEventSplittingEnabled(false)在源文件应该有帮助。将此属性设置为false将只允许一个视图进行单击。你可以在这里阅读

在情况2中,会有一些东西延迟导航过程,允许用户多次单击视图(API调用,动画等)。如果可能的话,应该解决根本问题,以便即时进行导航,不允许用户两次单击视图。如果延迟是不可避免的,就像在API调用的情况下,禁用视图或使其不可点击将是适当的解决方案。

将我的答案优雅地扔到处理两种情况(双击,同时点击两个按钮)的环中,但尽量不掩盖真正的错误。

我们可以使用navigateSafe()函数来检查我们试图导航到的目的地从当前目的地是否是无效的,但从前一个目的地是否是有效的。如果是这种情况,代码假设用户双击或同时点击两个按钮。

然而,这个解决方案并不完美,因为它可能会掩盖一些小众情况下的实际问题,即我们试图导航到恰好是父端的目的地。但据推测,这种情况不太可能发生。

代码:

fun NavController.navigateSafe(directions: NavDirections) {
    val navigateWillError = currentDestination?.getAction(directions.actionId) == null

    if (navigateWillError) {
        if (previousBackStackEntry?.destination?.getAction(directions.actionId) != null) {
            // This is probably some user tapping two different buttons or one button twice quickly
            // Ignore...
            return
        }

        // This seems like a programming error. Proceed and let navigate throw.
    }

    navigate(directions)
}