Jetpack Navigation을 사용하다 다음과 같은 에러를 뱉고 앱이 죽은 경험을 한 적이 있다.
"Navigation action cannot be found in the current destination"
해당 글에 의하면
같은 navigation action을 연속해서 호출해서 발생하는 문제이기 때문에 연속해서 호출되는 것을 막는 방법으로 해결할 수 있다.
이를 해결하기 위한 두 가지의 방법중 safeNavigate라는 확장함수를 만드는 방법을 추천한다.
해당 확장함수는 current destination이 존재하지 않을 경우 navigation action 이 trigger 되지 않도록 설계되었기 때문에 에러의 대한 해결 방법으로 적합하다.
safeArgs 와 연계해서 사용하면 된다.
fun NavController.safeNavigate(direction: NavDirections) {
currentDestination?.getAction(direction.actionId)?.run { navigate(direction) }
}
fun NavController.safeNavigate(
@IdRes currentDestinationId: Int,
@IdRes id: Int,
args: Bundle? = null
) {
if (currentDestinationId == currentDestination?.id) {
navigate(id, args)
}
}
블로그에서 제시한 사용 예시이다.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btn_open_screen_two.setOnClickListener {
findNavController().safeNavigate(FragmentOneDirections.actionFragmentOneToFragmentTwo())
}
btn_double_click.setOnClickListener {
performDoubleClick()
}
}
private fun performDoubleClick() {
for (i in 1 downTo 0) {
btn_open_screen_two.performClick()
}
}
fun NavController.safeNavigate(direction: NavDirections) {
Log.d(clickTag, "Click happened")
currentDestination?.getAction(direction.actionId)?.run {
Log.d(clickTag, "Click Propagated")
navigate(direction)
}
}
내가 사용한 방법은 다음과 같다.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
bind {
vm = registerLessonViewModel
}
initViews()
initObserver()
}
private fun initObserver() = with(registerLessonViewModel) {
repeatOnStarted {
launch {
onNavigateToRegisterLessonCheckClick
.collect {
registerLessonViewModel.setLessonInfo()
navigateToRegisterLessonCheck()
}
}
private fun navigateToRegisterLessonCheck() {
val action = RegisterLessonSecondFragmentDirections.actionRegisterLessonSecondToRegisterLessonCheck()
findNavController().safeNavigate(action)
}
sharedViewModel 을 통해 프래그먼트간의 데이터를 공유하는 방법을 사용하였기 때문에 인자를 넘겨주진 않았는데, 인자를 넘겨줄 필요가 있을 경우 safeArgs 을 이용하여 complie time에 validation을 할 수 있어 안전하게 데이터를 넘겨줄 수 있다.