参数异常:导航目标 xxx 在此 NavController 中未知。

226

我在使用新的Android Navigation Architecture组件时遇到了问题,当我尝试从一个片段导航到另一个时,我会收到这个奇怪的错误:

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

除了这个特定的导航之外,其他导航都正常工作。

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

将不胜感激您的任何帮助。


请提供一些代码以便更好地理解。 - Alex
到目前为止,随着库的新版本的发布,这个bug的出现率已经降低了,但我认为这个库的文档还不够完善。 - Jerry Okafor
40个回答

1
如果您点击得太快,会导致空值和崩溃。
我们可以使用RxBinding库来解决这个问题。在单击发生之前,您可以添加节流和持续时间。
 RxView.clicks(view).throttleFirst(duration, TimeUnit.MILLISECONDS)
            .subscribe(__ -> {
            });

这些关于Android限速的文章可能会有所帮助。干杯!

0

我在我的项目中遇到了同样的问题,最初我尝试对触发导航操作的视图进行防抖处理。但经过一些实验后,我发现在非常慢的设备上,防抖时间应该设置得非常高,这会导致拥有快速设备的用户感受到应用变慢。

因此,我提出了以下NavController扩展API,它与原始API相符并且易于使用:

fun NavController.safeNavigate(directions: NavDirections) {
    try {
        currentDestination?.getAction(directions.actionId) ?: return
        navigate(directions.actionId, directions.arguments, null)
    } catch (e : Exception) {
        logError("Navigation error", e)
    }
}

fun NavController.safeNavigate(directions: NavDirections, navOptions: NavOptions?) {
    try {
        currentDestination?.getAction(directions.actionId) ?: return
        navigate(directions.actionId, directions.arguments, navOptions)
    } catch (e : Exception) {
        logError("Navigation error", e)
    }
}

fun NavController.safeNavigate(directions: NavDirections, navigatorExtras: Navigator.Extras) {
    try {
        currentDestination?.getAction(directions.actionId) ?: return
        navigate(directions.actionId, directions.arguments, null, navigatorExtras)
    } catch (e : Exception) {
        logError("Navigation error", e)
    }
}

请注意,我正在使用SafeArgs和NavDirections。这些函数会检查当前目标是否有效,并且仅在操作不为空时进行导航。如果导航库每次返回正确的操作,则不需要try catch部分,但我想消除所有可能的崩溃。

0

这件事发生在我身上,我的问题是我在选项卡项目片段上点击了一个FAB。我试图从一个选项卡项目片段导航到另一个片段

但根据 Ian Lake此答案中所说,我们必须使用tablayoutviewpager没有导航组件支持。因此,从包含选项卡的片段到选项卡项目片段没有导航路径。

例如:

containing fragment -> tab layout fragment -> tab item fragment -> another fragment

解决方案是创建从选项卡布局包含的片段到目标片段的路径 例如:路径:容器片段 -> 另一个片段 缺点:
  • 导航图不再准确表示用户流程。

0
我为Fragment创建了这个扩展函数:
fun Fragment.safeNavigate(
    @IdRes actionId: Int,
    @Nullable args: Bundle? = null,
    @Nullable navOptions: NavOptions? = null,
    @Nullable navigatorExtras: Navigator.Extras? = null
) {
    NavHostFragment.findNavController(this).apply {
        if (currentDestination?.label == this@safeNavigate::class.java.simpleName) {
            navigate(actionId, args, navOptions, navigatorExtras)
        }
    }
}

0

0

这个错误可能是因为您将目标屏幕分配给了错误的图表。


什么是解决方案? - IgorGanapolsky
1
@IgorGanapolsky 将您的“导航”屏幕替换为右侧的图表。 - Neuron

0
如果您正在使用RecyclerView,请在单击操作中添加一个冷却时间,并在RecyclerView的XML文件中使用android:splitMotionEvents ="false"

1
看看我的下面的答案。 - Crazy

0
通常当我遇到这种情况时,我会遇到Charles Madere所描述的问题:在同一个UI上触发了两个导航事件,一个改变了currentDestination,另一个因为currentDestination被更改而失败。如果您双击或单击调用findNavController.navigate的两个视图,则可能会发生这种情况。
因此,要解决这个问题,您可以使用if-checks、try-catch或者如果您感兴趣,还有一个findSafeNavController(),它会在导航之前为您执行这些检查。它还有一个lint-check,以确保您不会忘记这个问题。 GitHub 详细说明该问题的文章

0

更新了@Alex Nuts的解决方案

如果对于特定片段没有操作并且想要导航到该片段

fun NavController.navigateSafe(
@IdRes actionId: Int, @IdRes fragmentId: Int, args: Bundle? = null,
navOptions: NavOptions? = null, navExtras: Navigator.Extras? = null) 
{
  if (actionId != 0) {
      val action = currentDestination?.getAction(actionId) ?: graph.getAction(actionId)
      if (action != null && currentDestination?.id != action.destinationId) {
          navigate(actionId, args, navOptions, navExtras)
    }
    } else if (fragmentId != 0 && fragmentId != currentDestination?.id)
        navigate(fragmentId, args, navOptions, navExtras)
}

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接