在NavController中避免Android导航IllegalArgumentException

Mic*_* A. 7 android android-architecture-navigation

我最近切换到Android导航,但是遇到了很多情况(在代码的不同部分),我得到:

Fatal Exception: java.lang.IllegalArgumentException
navigation destination com.xxx.yyy:id/action_aFragment_to_bFragment is unknown to this NavController
Run Code Online (Sandbox Code Playgroud)

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

findNavController(this, R.id.navigation_host_fragment).navigate(R.id.action_aFragment_to_bFragment)
Run Code Online (Sandbox Code Playgroud)

通常是响应按钮按下。

目前尚不清楚为什么会引发此错误。我目前的怀疑是,onClickListener在某些设备上被某种程度上调用了两次,从而导致导航被第二次调用(导致当时处于错误状态)。引起这种怀疑的原因是,这似乎最经常发生在某些情况下,即在导航调用之前可能会有“长时间”运行的操作。但是,我无法在自己的设备上重新创建它。

关于如何避免此问题的想法(或者实际上,是该问题的真正根本原因是什么)?

我不想使用全局动作;我对向堆栈引入更多意外状态持谨慎态度。而且,我真的希望不必在每次进行导航调用时都尝试测试当前状态。

Roh*_*man 24

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

if (findNavController().currentDestination?.id == R.id.currentFragment) {
        findNavController().navigate(R.id.action_current_next)
}
Run Code Online (Sandbox Code Playgroud)

  • 有没有办法获取 R.id.currentFragment? (3认同)
  • 这可行,但您需要找出为什么该函数被多次调用。就我而言,每次重新启动片段时,我都会注册一个观察者,并且它永远不会取消注册,因此随着时间的推移,它会累积调用。 (2认同)

Hus*_*dar 5

好的,让我向你解释这个异常是通过的,因为我们正在从一个片段(目的地)调用一个动作,它不是堆栈上的当前目的地。

即你正在调用一个动作

R.id.action_aFragment_to_bFragment
Run Code Online (Sandbox Code Playgroud)

从 fragmentA 但在 navController 当前目的地是其他那个 fragmentA。这就是为什么 navController 通过该异常:

navigation destination com.xxx.yyy:id/action_aFragment_to_bFragment is unknown to this NavController
Run Code Online (Sandbox Code Playgroud)

您可以在导航前检查当前目的地。喜欢

 Toast.makeText(context,view?.findNavController()?.currentDestination?.label,Toast.LENGTH_SHORT).show()
Run Code Online (Sandbox Code Playgroud)

这将显示您当前的目的地,我相信那将是其他目的地。

当我们替换动作以外的片段时(例如通过不带导航的旧方法)或我们在调用动作之前弹出该片段时,就会发生这种情况。

如果是这种情况,那么您必须使用Global Action,因为他们不在乎当前目的地是什么。