当我试图从一个片段导航到另一个片段时,我遇到了新的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。
任何帮助都将不胜感激。
当前回答
我解决了同样的问题,把检查之前导航,而不是样板代码点击即时控制
if (findNavController().currentDestination?.id == R.id.currentFragment) {
findNavController().navigate(R.id.action_current_next)}
/* Here R.id.currentFragment is the id of current fragment in navigation graph */
根据这个答案
https://stackoverflow.com/a/56168225/7055259
其他回答
您可以在导航控制器的当前目标中检查请求的操作。
更新 为安全导航增加了全局操作的使用。
fun NavController.navigateSafe(
@IdRes resId: Int,
args: Bundle? = null,
navOptions: NavOptions? = null,
navExtras: Navigator.Extras? = null
) {
val action = currentDestination?.getAction(resId) ?: graph.getAction(resId)
if (action != null && currentDestination?.id != action.destinationId) {
navigate(resId, args, navOptions, navExtras)
}
}
试试
创建以下扩展函数(或普通函数):
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
我的答案是:
我检查当前目的地是否属于当前片段。如果为真,则执行导航操作。
就这些!
在调用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)
}
发生此错误可能是因为您将目标屏幕分配给了错误的图形
更新到@AlexNuts回答以支持导航到嵌套图。当一个动作使用一个嵌套图作为目的地时,如下所示:
<action
android:id="@+id/action_foo"
android:destination="@id/nested_graph"/>
此操作的目的ID不能与当前目的进行比较,因为当前目的不能是图形。必须解析嵌套图的起始目的地。
fun NavController.navigateSafe(directions: NavDirections) {
// Get action by ID. If action doesn't exist on current node, return.
val action = (currentDestination ?: graph).getAction(directions.actionId) ?: return
var destId = action.destinationId
val dest = graph.findNode(destId)
if (dest is NavGraph) {
// Action destination is a nested graph, which isn't a real destination.
// The real destination is the start destination of that graph so resolve it.
destId = dest.startDestination
}
if (currentDestination?.id != destId) {
navigate(directions)
}
}
然而,这将防止导航到同一目的地两次,这是有时需要的。为了允许这一点,你可以添加一个检查action.navOptions?. shouldlaunchsingletop(),并添加app:launchSingleTop="true"的动作,你不希望重复的目的地。