当我试图从一个片段导航到另一个片段时,我遇到了新的Android导航架构组件的问题,我得到了这个奇怪的错误:
java.lang.IllegalArgumentException: navigation destination XXX
is unknown to this NavController
其他导航都很好,除了这个。
我使用Fragment的findNavController()函数来访问NavController。
任何帮助都将不胜感激。
当我试图从一个片段导航到另一个片段时,我遇到了新的Android导航架构组件的问题,我得到了这个奇怪的错误:
java.lang.IllegalArgumentException: navigation destination XXX
is unknown to this NavController
其他导航都很好,除了这个。
我使用Fragment的findNavController()函数来访问NavController。
任何帮助都将不胜感激。
当前回答
在调用navigate之前检查currentDestination可能会有帮助。
例如,如果您在导航图fragmentA和fragmentB上有两个片段目的地,并且从fragmentA到fragmentB只有一个动作。当你已经在fragmentB上时,调用navigate(R.id.action_fragmentA_to_fragmentB)将导致IllegalArgumentException。因此,在导航之前,你应该总是检查currentDestination。
if (navController.currentDestination?.id == R.id.fragmentA) {
navController.navigate(R.id.action_fragmentA_to_fragmentB)
}
其他回答
在我的案例中,错误发生是因为我在启动画面后启用了带有Single Top和Clear Task选项的导航操作。
为了防止崩溃,我采取了如下措施:
我有一个BaseFragment,在那里我添加了这个乐趣,以确保目的地是已知的currentDestination:
fun navigate(destination: NavDirections) = with(findNavController()) {
currentDestination?.getAction(destination.actionId)
?.let { navigate(destination) }
}
值得注意的是,我正在使用SafeArgs插件。
在我的情况下,我有多个导航图文件,我试图从一个导航图位置移动到另一个导航图的目的地。
为此,我们必须将第二个导航图像这样包含在第一个导航图中
<include app:graph="@navigation/included_graph" />
并将此添加到你的行动中:
<action
android:id="@+id/action_fragment_to_second_graph"
app:destination="@id/second_graph" />
其中second_graph为:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/second_graph"
app:startDestination="@id/includedStart">
在第二张图中。
更多信息请点击这里
正如在其他回答中提到的,此异常通常发生在用户
同时单击处理导航的多个视图 在处理导航的视图上多次单击。
使用计时器来禁用单击并不是处理此问题的合适方法。如果用户在计时器过期后还没有导航到目的地,应用程序无论如何都会崩溃,在许多情况下,导航不是执行的动作,快速点击是必要的。
在情况1中,android:splitMotionEvents=“false”在xml或setMotionEventSplittingEnabled(false)在源文件应该有帮助。将此属性设置为false将只允许一个视图进行单击。你可以在这里阅读
在情况2中,会有一些东西延迟导航过程,允许用户多次单击视图(API调用,动画等)。如果可能的话,应该解决根本问题,以便即时进行导航,不允许用户两次单击视图。如果延迟是不可避免的,就像在API调用的情况下,禁用视图或使其不可点击将是适当的解决方案。
我在我的项目中也有同样的问题,首先我试图在视图上触发导航动作的点击,但经过一些实验后,我发现在真正缓慢的设备上,debounce应该是一个非常高的值,导致应用程序对快速设备的用户感到缓慢。
所以我为NavController提出了以下扩展,我认为它符合原始的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。这些函数检查操作从当前目的地是否有效,并且仅在操作不为空时进行导航。如果Navigation库每次都返回正确的操作,那么try catch部分就不需要了,但我希望消除所有可能的崩溃。