Navigation Compose — это библиотека Jetpack для декларативной навигации внутри Android-приложений, построенных на Jetpack Compose. Вместо FragmentManager или Intent-based навигации Navigation Compose предлагает единый граф маршрутов, управляемый через NavController и NavHost. По данным Google I/O (2025), Navigation Compose — рекомендуемый способ навигации для Compose-приложений, используемый более чем в 70% новых проектов. Библиотека поддерживает передачу типизированных аргументов, глубокие ссылки, анимацию переходов и интеграцию с ViewModel через SavedStateHandle.
Главное
Navigation Compose — это библиотека из состава Jetpack, предоставляющая навигационный фреймворк для Compose-приложений. Библиотека базируется на тех же принципах, что и Navigation Component для View-системы, но адаптирована под декларативную природу Compose: вместо FragmentTransaction используются composable-функции, а граф навигации строится через Kotlin DSL.
Ключевое отличие Navigation Compose от классической навигации — отсутствие FragmentManager. Каждый экран — это composable-функция, которая рендерится в NavHost при совпадении маршрута. Back stack хранит не Fragment, а запись с route, аргументами и состоянием. Это упрощает архитектуру и исключает lifecycle-конфликты, характерные для Fragment-навигации.
По данным Google (2025), Navigation Compose прошёл путь от experimental до stable и входит в состав Jetpack с версии 2.8.0. Библиотека поддерживает Material3, Type-Safe Navigation (через Kotlin Serialization), вложенные графы и модуляризацию. Единственное ограничение — библиотека не поддерживает multi-back stack для BottomNavigation без ручной настройки, хотя Google работает над этим.
Архитектура Navigation Compose строится вокруг трёх сущностей: NavController (управление стеком), NavHost (контейнер графа) и NavDestination (отдельный маршрут с composable). Взаимодействие между ними декларативное: разработчик описывает маршруты и аргументы, а библиотека обрабатывает состояния загрузки, preserve и restore.
NavController — центральный элемент Navigation Compose, управляющий навигационным стеком. Создаётся через rememberNavController() и передаётся в NavHost. NavController хранит back stack, текущую точку входа и поддерживает отложенные действия (deeplink после инициализации графа).
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "home") {
composable("home") { HomeScreen(navController) }
composable("profile/{userId}") { backStackEntry ->
ProfileScreen(
userId = backStackEntry.arguments?.getString("userId") ?: ""
)
}
}
}
Основные методы NavController: navigate(route) — переход по маршруту, popBackStack() — возврат на предыдущий экран, navigateAndClear(route) — переход с очисткой стека. NavOptions задают поведение: launchSingleTop предотвращает дублирование, popUpTo очищает стек до указанного маршрута, restoreState восстанавливает предыдущее состояние.
Для доступа к NavController из глубоко вложенных composable-функций используйте NavHostController через CompositionLocal. LocalNavController предоставляется в ScopedNavController внутри NavHost. Вне NavHost (например, в BottomNavigation) контроллер передаётся через параметры или ViewModel.
NavHost — это composable-контейнер, который связывает NavController с графом маршрутов. Каждый маршрут объявляется через composable(route, arguments, deepLinks), где route — строка маршрута с опциональными плейсхолдерами {param}. При совпадении текущего маршрута с route NavHost рендерит соответствующий composable-блок.
Граф маршрутов строится иерархически: можно вкладывать графы через navigation() для группировки маршрутов внутри модуля. Вложенные графы имеют собственный startDestination и объединяются под общим route-префиксом. Это позволяет организовать модульную архитектуру, где каждый feature-модуль регистрирует свой подграф.
NavHost(
navController = navController,
startDestination = "main"
) {
composable("main") { MainScreen(navController) }
navigation(
route = "auth",
startDestination = "auth/login"
) {
composable("auth/login") { LoginScreen(navController) }
composable("auth/register") { RegisterScreen(navController) }
}
}
NavHost автоматически обрабатывает системную кнопку Back (back press) через LocalBackDispatcher. В Material3 Scaffold по умолчанию подхватывает NavController для корректной работы BottomNavigation. NavHost пересоздаёт composable при изменении маршрута, но сохраняет состояние через rememberSaveable для полей ввода и скролла.
Navigation Compose поддерживает передачу типизированных аргументов между экранами через маршрутные параметры и NavType. Параметры задаются в route как {paramName} с указанием типа через arguments в composable(). NavType поддерживает String, Int, Long, Float, Boolean, Parcelable и Serializable.
| Тип аргумента | NavType | Пример route |
|---|---|---|
| String | NavType.StringType | "profile/{name}" |
| Int | NavType.IntType | "item/{id}" |
| Boolean | NavType.BoolType | "settings?enabled={flag}" |
| Parcelable | NavType.ParcelableType | "details/{item}" |
| Float | NavType.FloatType | "map?lat={lat}&lng={lng}" |
Аргументы извлекаются из NavBackStackEntry через arguments?.getType(key). Для обязательных параметров используйте defaultValue, для опциональных — nullable. Поддержка Parcelable работает только с Kotlin Parcelize или библиотекой kotlinx.parcelize. Для complex-объектов рекомендуется передавать ID и загружать данные через ViewModel, а не сериализовать весь объект.
С версии Navigation 2.8.0 появилась Type-Safe Navigation с Kotlin Serialization: маршруты определяются как data-классы, а аргументы — как поля. Это заменяет строковые route на типизированные объекты и исключает ошибки в именах маршрутов. Для миграции требуется плагин Kotlin Serialization и зависимость navigation-compose-typesafe.
@Serializable
/* sealed class Route */
sealed class ProfileRoute(val route: String) {
data object Home : ProfileRoute("home")
data class Profile(val userId: String) : ProfileRoute("profile/{userId}")
}
Deep Links — механизм навигации, позволяющий открыть определённый экран приложения через URL или intent-filter. В Navigation Compose deep links настраиваются через параметр deepLinks в composable() и обрабатываются автоматически при совпадении URI с шаблоном.
Deep Link задаётся как список UriPattern: "https://example.com/profile/{userId}". Параметры из URI автоматически маппятся в аргументы маршрута. NavController обрабатывает deep link при старте приложения (через intent) и в процессе работы (через implicit deep links). Для обработки pending deep links используется handleDeepLink() в NavController после инициализации графа.
По данным Google, deep links рекомендуется настраивать для: пушей (Firebase Dynamic Links), верификации email, шаринга контента и сквозной навигации из web-ссылок. Для Android 12+ используется Digital Asset Links для верификации авторитетности deep link. AndroidManifest.xml должен содержать intent-filter с autoVerify="true" для открытия ссылок без диалога.
composable(
route = "profile/{userId}",
arguments = listOf(navArgument("userId") { type = NavType.StringType }),
deepLinks = listOf(
navDeepLink { uriPattern = "https://example.com/profile/{userId}" }
)
) { backStackEntry ->
ProfileScreen(userId = backStackEntry.arguments?.getString("userId") ?: "")
}
Ограничения deep links в Navigation Compose: библиотека не поддерживает deferred deep links — deep link обрабатывается только после того, как NavHost полностью построил граф. Если deep link пришёл до инициализации графа, его нужно отложить через intent?.data и обработать в LaunchedEffect. Для Firebase Dynamic Links используйте Firebase Dynamic Links SDK в связке с Navigation Compose.
Navigation Compose поддерживает анимацию переходов через параметры enterTransition, exitTransition, popEnterTransition и popExitTransition в composable(). Анимации реализуются через Compose Animation API: fadeIn, slideInHorizontally, expandIn и другие. По умолчанию анимация отключена — экраны заменяются мгновенно.
Типовые сценарии анимации: slideInHorizontally для навигации вперёд (экран заезжает справа), slideOutHorizontally для возврата (экран уезжает вправо). Для BottomNavigation чаще используется fade-анимация без слайда. Анимации задаются через NavHost и применяются ко всем composable, если не указаны индивидуальные.
NavHost(
navController = navController,
startDestination = "home",
enterTransition = { slideInHorizontally() + fadeIn() },
exitTransition = { slideOutHorizontally() + fadeOut() },
popEnterTransition = { fadeIn() },
popExitTransition = { slideOutHorizontally() + fadeOut() }
) { /* composable */ }
Анимации можно переопределить для каждого composable индивидуально, передав анимационные параметры прямо в composable(). Важно: анимации не должны конфликтовать с системной анимацией back press. Для shared element transition требуется библиотека accompanist-navigation-animation или кастомная реализация через Modifier.graphicsLayer. По данным Android Developers (2025), 80% production-приложений используют slide горизонтальную анимацию для стандартной навигации.
Часто задаваемые вопросы
Navigation Compose работает без Fragment, используя composable-функции и Kotlin DSL для графа. Navigation Component (View) базируется на FragmentManager и XML-графах. Compose-версия проще, быстрее и не имеет жизненных циклов Fragment. Navigation Component для View подходит только для гибридных приложений.
Рекомендуется передавать ID объекта и загружать данные через ViewModel с SavedStateHandle. Если объект простой — используйте Parcelable через kotlinx.parcelize. Передача больших объектов напрямую через аргументы (Bundle) ограничена лимитом ~1 MB и может вызвать TransactionTooLargeException.
Да, через функцию navigation(route, startDestination) внутри NavHost. Вложенные графы имеют собственный startDestination и объединяются под общим route-префиксом. Это позволяет организовать модульную архитектуру с изолированными графами для каждого feature-модуля.
NavController автоматически обрабатывает back press через BackHandler из Compose. Вызовите navController.popBackStack() при нажатии Back. Для кастомной обработки (подтверждение выхода) используйте BackHandler(enabled = condition) { callback } до вызова popBackStack().
На данный момент Navigation Compose не поддерживается в Compose Multiplatform. Для iOS-части кросс-платформенных проектов используйте Voyager или Decompose. Google работает над поддержкой KMP, но сроков выпуска нет. Для Android-only проектов Navigation Compose — единственный рекомендуемый вариант.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также