Navigation Compose: какво е, архитектура и работа в разработката

Автор: IT Sectr Публикувано: 2026-06-29 Време за четене: 8 мин

Navigation Compose — е библиотека Jetpack за декларативна навигация в Android приложения, изградени на Jetpack Compose. Вместо FragmentManager или навигация, базирана на Intent, Navigation Compose предлага единна графа от маршрути, управлявана чрез NavController и NavHost. Според данни от Google I/O (2025), Navigation Compose е препоръчителният начин за навигация за Compose приложения, използван в повече от 70% от новите проекти. Библиотеката поддържа предаване на типизирани аргументи, дълбоки връзки, анимация на преходи и интеграция с ViewModel чрез SavedStateHandle.

Основни точки

  • Navigation Compose — библиотека Jetpack за декларативна навигация в Compose с единна графа от маршрути
  • NavController — централният контролер, управляващ стека за навигация и състоянието на back stack
  • NavHost — контейнер, определящ графата от маршрути чрез composable функции с route
  • Аргументите се предават чрез NavType и SavedStateHandle с поддръжка на типизирани параметри
  • Deep Links — навигация чрез външни URL с автоматично разпознаване на аргументи от URI

Какво е Navigation Compose?

Navigation Compose — е библиотека от пакета Jetpack, предоставяща навигационна рамка за Compose приложения. Библиотеката се основава на същите принципи като Navigation Component за View системата, но е адаптирана към декларативната природа на Compose: вместо FragmentTransaction се използват composable функции, а навигационната графа се изгражда чрез Kotlin DSL.

Ключовата разлика между Navigation Compose и класическата навигация — липсата на FragmentManager. Всеки екран е composable функция, която се рендерира в NavHost при съвпадение на маршрута. Back stack съхранява не Fragment, а запис с route, аргументи и състояние. Това опростява архитектурата и елиминира конфликтите на жизнения цикъл, характерни за 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). Взаимодействието между тях е декларативно: разработчикът описва маршрутите и аргументите, а библиотеката обработва състоянията на зареждане, запазване и възстановяване.

NavController — централният елемент на Navigation Compose, управляващ навигационния стек. Създава се чрез rememberNavController() и се предава на NavHost. NavController съхранява back stack, текущата точка на влизане и поддържа отложени действия (deeplink след инициализация на графата).

kotlin
@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 е низ на маршрут с опционални placeholders {param}. При съвпадение на текущия маршрут с route, NavHost рендерира съответния composable блок.

Графата от маршрути се изгражда йерархично: графите могат да се влагат чрез navigation() за групиране на маршрути в рамките на модул. Вложените графи имат собствен startDestination и се обединяват под общ route-префикс. Това позволява организиране на модулна архитектура, където всеки feature-модул регистрира своя подграф.

kotlin
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 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
StringNavType.StringType"profile/{name}"
IntNavType.IntType"item/{id}"
BooleanNavType.BoolType"settings?enabled={flag}"
ParcelableNavType.ParcelableType"details/{item}"
FloatNavType.FloatType"map?lat={lat}&lng={lng}"

Аргументите се извличат от NavBackStackEntry чрез arguments?.getType(key). За задължителни параметри използвайте defaultValue, за опционални — nullable. Поддръжката на Parcelable работи само с Kotlin Parcelize или библиотеката kotlinx.parcelize. За сложни обекти се препоръчва предаване на ID и зареждане на данни чрез ViewModel, а не сериализация на целия обект.

От версия Navigation 2.8.0 е налична Type-Safe Navigation с Kotlin Serialization: маршрутите се дефинират като data класове, аргументите като полета. Това заменя низовите route с типизирани обекти и елиминира грешки в имената на маршрути. За миграция е необходим plugin Kotlin Serialization и зависимостта navigation-compose-typesafe.

kotlin
@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 дълбоките връзки се конфигурират чрез параметъра deepLinks в composable() и се обработват автоматично при съвпадение на URI с шаблона.

Deep Link се задава като списък UriPattern: "https://example.com/profile/{userId}". Параметрите от URI автоматично се映射ват към аргументите на маршрута. NavController обработва дълбоката връзка при стартиране на приложението (чрез intent) и по време на работа (чрез implicit deep links). За обработка на чакащи дълбоки връзки се използва handleDeepLink() в NavController след инициализация на графата.

Според Google, конфигурирането на дълбоки връзки се препоръчва за: push известия (Firebase Dynamic Links), потвърждение на имейл, споделяне на съдържание и навигация от уеб връзки. За Android 12+ се използват Digital Asset Links за потвърждение на авторитета на дълбоката връзка. AndroidManifest.xml трябва да съдържа intent-filter с autoVerify="true" за отваряне на връзки без диалог.

kotlin
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") ?: "")
}

Ограничения на дълбоките връзки в Navigation Compose: библиотеката не поддържа отложени дълбоки връзки — дълбоката връзка се обработва едва след като NavHost напълно изгради графата. Ако дълбоката връзка пристигне преди инициализация на графата, трябва да се отложи чрез 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, ако не са посочени индивидуални.

kotlin
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% от производствените приложения използват хоризонтална slide анимация за стандартна навигация.

Често задавани въпроси

Как се различава Navigation Compose от Navigation Component за View?

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 Compose вложени графи?

Да, чрез функцията navigation(route, startDestination) вътре в NavHost. Вложените графи имат собствен startDestination и се обединяват под общ route-префикс. Това позволява организиране на модулна архитектура с изолирани графи за всеки feature-модул.

Как да обработя системния бутон Назад в Navigation Compose?

NavController автоматично обработва back press чрез BackHandler от Compose. Извикайте navController.popBackStack() при натискане на бутона Назад. За персонализирана обработка (потвърждение на изход) използвайте BackHandler(enabled = condition) { callback } преди извикване на popBackStack().

Може ли Navigation Compose да се използва с Jetpack Compose Multiplatform?

Към момента Navigation Compose не се поддържа в Compose Multiplatform. За iOS частта на cross-platform проекти използвайте Voyager или Decompose. Google работи върху поддръжка на KMP, но няма дати за пускане. За проекти само за Android, Navigation Compose е единствената препоръчителна опция.

Резюме

  • Navigation Compose — библиотека Jetpack за декларативна навигация в Compose, работеща чрез графа от маршрути и NavController
  • NavController управлява back stack и предоставя методи navigate, popBackStack за навигация
  • NavHost свързва контролера с графата чрез composable(), поддържайки вложени графи за модулна архитектура
  • Аргументите се предават чрез NavType с поддръжка на String, Int, Parcelable и Type-Safe Navigation с Kotlin Serialization
  • Deep Links се конфигурират чрез navDeepLink с UriPattern за външна навигация от URL и push известия
  • Анимация на преходите се задава чрез enterTransition, exitTransition с използване на Compose Animation API
  • Библиотеката не поддържа KMP и multi-back stack за BottomNavigation без допълнителна конфигурация

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също