Ошибка "Navigation destination xxx is unknown to this NavController" в Jetpack Navigation
Причина ошибки
Ошибка возникает, когда NavController, к которому вы обращаетесь из FragmentA, не знает о пункте назначения action_fragmentA_to_fragmentB. Это происходит, если NavController, полученный через findNavController(), принадлежит не тому NavHostFragment, который содержит ваш навигационный граф.
Основные сценарии возникновения
- Вызов из неправильного контекста — например, из диалогового фрагмента, вложенного фрагмента или адаптера.
- Фрагмент не привязан к NavHost — если FragmentA не является прямым потомком NavHostFragment.
- Неверный NavController в Activity — если вы получаете NavController из Activity, а не из фрагмента.
Решение: используйте правильный NavController
Самый надёжный способ — получить NavController из View, который гарантированно находится внутри NavHostFragment:
class FragmentA : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// ВАРИАНТ 1: Используем view.findNavController() (рекомендуется)
button.setOnClickListener {
view.findNavController().navigate(R.id.action_fragmentA_to_fragmentB)
}
// ВАРИАНТ 2: Используем requireActivity() если фрагмент вложен
// button.setOnClickListener {
// requireActivity().findNavController(R.id.nav_host_fragment)
// .navigate(R.id.action_fragmentA_to_fragmentB)
// }
}
}
Дополнительные проверки
- Убедитесь, что NavHostFragment имеет правильный ID — в вашей Activity должен быть:
<androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" app:navGraph="@navigation/nav_graph" ... /> - Проверьте, что action определён в том же графе — action должен быть внутри того же
<fragment>, откуда вы вызываете навигацию. - Если используете BottomNavigationView — передайте правильный NavController в setupWithNavController.
Почему это работает?
Метод View.findNavController() поднимается по иерархии View и находит ближайший NavController. Если FragmentA не является прямым потомком NavHostFragment (например, вложен в другой фрагмент), то findNavController() может вернуть NavController родительского фрагмента, который не знает о действиях дочернего графа. В этом случае используйте requireActivity().findNavController(R.id.nav_host_fragment) для явного указания ID.
Также проверьте, что у вас нет конфликта версий библиотек — убедитесь, что все модули используют одинаковую версию androidx.navigation:navigation-fragment-ktx.
Альтернативный подход: использование Safe Args
Вместо прямого вызова navigate(R.id.action...) рекомендую использовать плагин Safe Args. Это исключает ошибки с идентификаторами на этапе компиляции и делает код типобезопасным.
Как подключить Safe Args
- Добавьте в корневой
build.gradle:buildscript { dependencies { classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.7.7" } } - Добавьте в
build.gradleмодуля:plugins { id 'androidx.navigation.safeargs.kotlin' } - Теперь вы можете использовать сгенерированные классы:
class FragmentA : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) button.setOnClickListener { val action = FragmentADirections.actionFragmentAToFragmentB() view.findNavController().navigate(action) } } }
Преимущества
- Ошибка "unknown destination" будет обнаружена на этапе компиляции, а не в рантайме.
- Автоматическая генерация классов для передачи аргументов между фрагментами.
- Упрощает рефакторинг — при изменении ID действия IDE подсветит все места использования.
Если после перехода на Safe Args ошибка сохраняется — проблема точно в неправильном NavController, и нужно применить первый ответ.