避免在NavController中出现Android导航非法参数异常

20

我最近转换到了Android Navigation,但是在代码的不同部分遇到了相当多的情况,出现了以下问题:

Fatal Exception: java.lang.IllegalArgumentException
navigation destination com.xxx.yyy:id/action_aFragment_to_bFragment is unknown to this NavController

在每种情况下,代码都是简单的函数调用,例如:

findNavController(this, R.id.navigation_host_fragment).navigate(R.id.action_aFragment_to_bFragment)

通常是响应按钮按下的操作。

目前不清楚为什么会出现这个错误。我目前怀疑的是在某些设备上onClickListener被调用了两次,导致导航被第二次调用(因此它在那时处于错误的状态)。这种怀疑的原因是它似乎最常发生在导航之前有“长时间”运行的操作的情况下。但我自己的设备上无法重现这个问题。

如何避免这个问题(或者说,这个问题的实际根本原因是什么)?

我不想使用全局操作;我担心会给后台堆栈带来更多意外的状态。而且我真的不想每次进行导航调用时都尝试测试当前状态。

2个回答

26

在导航之前,您可以使用以下代码检查当前目的地是否正确。这将确保调用仅来自当前片段。通过同时点击两个视图(列表中的两个项目),可以重现此问题。

if (findNavController().currentDestination?.id == R.id.currentFragment) {
        findNavController().navigate(R.id.action_current_next)
}

1
到目前为止,我看到的最好(也是唯一)的处理方法。如果您连续非常快地按下按钮(即在视图刷新之前按下按钮),问题也可能会发生。导航库如此棘手且容易“跳出”其片段,这真是令人恼火。 - Michael A.
2
这个可以运行,但你需要找出为什么函数被调用了多次。在我的情况下,每次片段重新启动时我都会注册一个观察者,但它从未被注销,因此随着时间的推移它会累积调用。 - Dominique Lorre
3
有没有一种方法可以获取R.id.currentFragment? - Jachumbelechao Unto Mantekilla
如果我们需要传递参数怎么办? - IgorGanapolsky
@JachumbelechaoUntoMantekilla,对于你来说,currentDestionation.id也没有匹配到任何R.id吗?对我来说,它们在完全不同的范围内:21312307901000066 - riezebosch

5

好的,让我解释一下,这个异常被通过是因为我们在从一个不在当前堆栈中的片段(目标)中调用一个操作。

也就是说,你正在调用一个操作

R.id.action_aFragment_to_bFragment

来自fragmentA,但在navController中当前目标不是fragmentA。这就是为什么navController会抛出异常的原因:

navigation destination com.xxx.yyy:id/action_aFragment_to_bFragment is unknown to this NavController

在导航前,您可以检查当前的目标地点。例如:

 Toast.makeText(context,view?.findNavController()?.currentDestination?.label,Toast.LENGTH_SHORT).show()

这将会显示当前目的地,我相信还会有其他目的地。

当我们替换一个片段而不是操作时(比如使用旧方法而不是导航),或者在调用操作之前弹出该片段,就会发生这种情况。

如果是这种情况,那么你必须使用全局操作,因为它们不关心当前目的地是什么。


我知道为什么会触发异常。而弹出一个Toast并不能真正帮助我,因为这是生产代码(成千上万的用户中只有少数人遇到此错误),正如我所说,我无法在我拥有的任何设备上重现此问题。如果我能够重现,我就已经解决了这个问题。此应用程序中也没有实现导航框架之外的导航 - 这就是进行重写的原因,现在看到了这个问题的出现。 - Michael A.
toast只是为了澄清一下...我之前描述的问题很多人都遇到过,包括我自己。如果不是这种情况的话,那就是库中的一个bug。你知道这个库还处于beta状态。 - Hussnain Haidar
我正在使用这两个库,而且没有收到任何错误。implementation 'android.arch.navigation:navigation-fragment-ktx:1.0.0-beta01' implementation 'android.arch.navigation:navigation-ui-ktx:1.0.0-beta01' - Hussnain Haidar
有些人遇到这个问题是因为他们使用的是旧版本的库。 - Hussnain Haidar
1
关于旧版本的事情。一年后,我正在与这个无聊的问题作斗争,版本号是v2.2.1。 - Pedro Rodrigues

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