I've tried many solutions but I went with the most simple one.
If we take a look in the NavController#navigate method source code, it contains some complex logic.
If we decide to create a custom navigateSafe extension that resolves destination instead of NavController#navigate method, it may result in some unhandled issues in complex applications.
I suggest to wrap NavController#navigate calls in try/catch. Something like this:
@JvmOverloads
fun NavController.navigateSafe(
@IdRes resId: Int,
args: Bundle? = null,
navOptions: NavOptions? = null
) {
try {
navigate(resId, args, navOptions)
} catch (e: Throwable) {
if (BuildConfig.DEBUG) {
Timber.e(e)
} else {
throw e
}
}
}
@JvmOverloads
fun NavController.navigateSafe(direction: NavDirections, navOptions: NavOptions? = null) {
try {
navigate(direction, navOptions)
} catch (e: Throwable) {
if (BuildConfig.DEBUG) {
Timber.e(e)
} else {
throw e
}
}
}
In the catch block, we can simply log the error but I also suggest to rethrow this error in development builds(In case we mess up during the development) and track this error in the Crashlytics in production builds.