当我试图从一个片段导航到另一个片段时,我遇到了新的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。
任何帮助都将不胜感激。
当前回答
为了防止崩溃,我采取了如下措施:
我有一个BaseFragment,在那里我添加了这个乐趣,以确保目的地是已知的currentDestination:
fun navigate(destination: NavDirections) = with(findNavController()) {
currentDestination?.getAction(destination.actionId)
?.let { navigate(destination) }
}
值得注意的是,我正在使用SafeArgs插件。
其他回答
还有另一种解决快速点击导航崩溃问题的方法:
fun NavController.doIfCurrentDestination(@IdRes destination: Int, action: NavController.()-> Unit){
if(this.currentDestination?.id == destination){action()}
}
然后像这样使用:
findNavController().doIfCurrentDestination(R.id.my_destination){ navigate(...) }
这种解决方案的好处是,您可以轻松地用您已经使用的任何签名包装任何现有的naagte()调用,而不需要进行一百万次重载
发生此错误可能是因为您将目标屏幕分配给了错误的图形
更新的@Alex坚果解决方案
如果没有特定片段的操作,并希望导航到片段
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)
}
您可以在导航控制器的当前目标中检查请求的操作。
更新 为安全导航增加了全局操作的使用。
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)
}
}
在思考了Ian Lake在推特上的建议后,我想出了以下方法。将NavControllerWrapper定义如下:
class NavControllerWrapper constructor(
private val navController: NavController
) {
fun navigate(
@IdRes from: Int,
@IdRes to: Int
) = navigate(
from = from,
to = to,
bundle = null
)
fun navigate(
@IdRes from: Int,
@IdRes to: Int,
bundle: Bundle?
) = navigate(
from = from,
to = to,
bundle = bundle,
navOptions = null,
navigatorExtras = null
)
fun navigate(
@IdRes from: Int,
@IdRes to: Int,
bundle: Bundle?,
navOptions: NavOptions?,
navigatorExtras: Navigator.Extras?
) {
if (navController.currentDestination?.id == from) {
navController.navigate(
to,
bundle,
navOptions,
navigatorExtras
)
}
}
fun navigate(
@IdRes from: Int,
directions: NavDirections
) {
if (navController.currentDestination?.id == from) {
navController.navigate(directions)
}
}
fun navigateUp() = navController.navigateUp()
fun popBackStack() = navController.popBackStack()
}
然后在导航代码中:
val navController = navControllerProvider.getNavController()
navController.navigate(from = R.id.main, to = R.id.action_to_detail)