NavHost — шта је то, изградња графа и руте у Jetpack Compose-у

Аутор: IT Sectr Објављено: 2026-06-30 Време читања: 7 мин

NavHost је composable контејнер који служи као улазна тачка за граф навигације у Jetpack Compose-у. Он повезује NavController са скупом рута и приказује тренутни екран у зависности од стања back stack-а. Према Android Developers (2025), NavHost је обавезна компонента за сваку Compose апликацију са навигацијом. Унутар NavHost-а региструју се composable руте са опционим аргументима, deep links и анимацијом. Свака рута је обична composable функција која прима NavBackStackEntry са подацима прелаза. NavHost аутоматски обрађује back press, чување стања и враћање при реконфигурацији.

Главне тачке

  • NavHost — composable контејнер који повезује NavController са графом рута и приказује тренутни екран
  • composable() — функција регистрације руте са route, аргументима, deep links и анимацијом прелаза
  • startDestination — почетна рута која се отвара при креирању NavHost-а
  • Аргументи се задају кроз navArgument са NavType за типизовани пренос података између екрана
  • Анимација се подешава глобално или индивидуално кроз enterTransition, exitTransition параметре

Шта је NavHost у Jetpack Compose-у?

NavHost је composable функција која обезбеђује контејнер за приказ тренутног екрана навигације. NavHost прима NavController, startDestination и граф рута изграђен кроз Kotlin DSL. При промени тренутне руте, NavHost пребацује приказани composable са задатом анимацијом.

NavHost ради као прекидач екрана: прати тренутни NavBackStackEntry из NavController-а и приказује одговарајући composable блок. Сваки екран је независна composable функција која прима NavBackStackEntry са аргументима руте. Сви екрани постоје у јединственом стаблу композиције, али NavHost приказује само један, скривајући остале кроз анимацију.

За разлику од FragmentManager-а, NavHost не креира Fragment за сваки екран. Цео lifecycle се управља кроз CompositionLifecycle — composable функције немају onStart/onResume, па се за side-ефекте користе LaunchedEffect и DisposableEffect. NavHost се аутоматски претплаћује на NavController и прекомпонује UI при промени руте.

Према Google-у, NavHost је стабилни API од верзије Navigation 2.4.0. Од верзије 2.8.0, NavHost подржава Type-Safe Navigation кроз Kotlin Serialization, што замењује string руте са data-класама. NavHost такође подржава угнежђене графове, што омогућава организовање навигације по модулима.

NavHost се креира са два обавезна параметра: navController (инстанца NavHostController-а) и startDestination (стринг руте првог екрана). Трећи параметар — builder блок, у коме се региструју све руте кроз composable(), navigation() и dialog().

kotlin
@Composable
fun AppNavHost(navController: NavHostController) {
    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        composable("home") { HomeScreen(navController) }
        composable("settings") { SettingsScreen(navController) }
    }
}

startDestination је рута која се отвара при првом покретању NavHost-а. Ако је back stack празан, NavHost аутоматски додаје startDestination у стек. При реконфигурацији (ротација екрана) NavHost враћа последњу руту из savedState-а, а не startDestination.

За BottomNavigation, startDestination је једна од рута доњег панела. Остале руте панела се додају као засебни composable записи. NavHost треба да се постави унутар Scaffold.content — тамо где се приказује главни садржај апликације. NavHost заузима целу доступну висину умањену за TopAppBar и BottomNavigation.

Регистрација рута кроз composable

Функција composable(route, arguments, deepLinks, enterTransition, exitTransition, content) региструје руту у графу NavHost-а. Параметар route је стринг који описује путању са опционим placeholder-има облика {paramName}. Placeholder се замењује конкретном вредношћу при навигацији.

Content блок прима NavBackStackEntry из којег се извлаче аргументи. Composable функција екрана се приказује само када тренутна рута NavController-а одговара route. При неусаглашености, composable се уклања из композиције, али његово стање може бити сачувано кроз rememberSaveable или ViewModel са SavedStateHandle.

kotlin
composable(
    route = "article/{articleId}",
    arguments = listOf(navArgument("articleId") {
        type = NavType.IntType
        defaultValue = 0
    }),
    deepLinks = listOf(navDeepLink { uriPattern = "https://app.example/article/{articleId}" })
) { backStackEntry ->
    val articleId = backStackEntry.arguments?.getInt("articleId") ?: 0
    ArticleScreen(articleId = articleId)
}

Број composable записа унутар NavHost-а може бити било који — од пар до стотина. За велике апликације, руте се деле по модулима и повезују кроз угнежђене графове. Сваки composable може имати сопствена подешавања анимације, deep links и аргумената.

Аргументи и типизовани параметри рута

Аргументи руте се дефинишу кроз параметар arguments: List<NamedNavArgument> у composable(). Сваки аргумент се задаје кроз navArgument(name) { type; defaultValue }. NavType одређује тип аргумента: StringType, IntType, LongType, FloatType, BoolType, ParcelableType и ReferenceType.

Параметар рутеПример routeNavType
Путања (path)„user/{id}"NavType.IntType
Упит (query)„search?q={query}"NavType.StringType
Опциони„details/{id}?tab={tab}"StringType + defaultValue=""
Parcelable„checkout/{order}"NavType.ParcelableType

Аргументи се извлаче из NavBackStackEntry кроз arguments?.getInt("id"). За обавезне аргументе, defaultValue може изостати — NavType ће користити null. За опционе аргументе, defaultValue је обавезан, иначе ће навигација бацити изузетак при одсуству параметра.

Од верзије Navigation 2.8.0 препоручује се Type-Safe Navigation: дефинишите sealed class или data class за руте са Kotlin Serialization. Уместо string route-а, користите composable<RouteType> { backStackEntry -> }. Ово елиминише грешке у куцању route-а и аутоматски генерише NavType за аргументе. За миграцију, додајте зависимост navigation-compose-typesafe и прикључак Kotlin Serialization.

Угнежђени графови навигације

nested graphs — механизам груписања рута унутар NavHost-а кроз функцију navigation(route, startDestination). Угнежђени граф има сопствени route префикс и startDestination, а све његове руте су доступне кроз префикс. nested graphs се користе за модуларну архитектуру, где сваки feature модул региструје свој подграф.

Предности угнежђених графова: изолација рута унутар модула, јединствени back stack за групу екрана, могућност навигације по префиксу без откривања унутрашње структуре. На пример, граф „auth" садржи „auth/login" и „auth/register". Навигација је могућа како по пуној рути, тако и по префиксу са преусмеравањем на startDestination.

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) }
    }
}

nested graphs подржавају пренос аргумената на нивоу графа: параметри декларисани у route-у графа преносе се на све унутрашње руте. За чишћење угнежђеног графа користите popBackStack(route) — уклониће све унутрашње записе. Угнежђени графови немају ограничење дубине, али се препоручује не више од 3 нивоа за читљивост.

Анимација и прилагођавање прелаза

NavHost подржава анимацију прелаза између composable рута кроз параметре enterTransition, exitTransition, popEnterTransition и popExitTransition. Анимације се дефинишу једном за NavHost и примењују на све руте, или индивидуално за сваки composable. Подразумевано, анимација је искључена.

Типична конфигурација: enterTransition = slideInHorizontally(initialOffsetX = { it }) — екран улази са десне стране; exitTransition = slideOutHorizontally(targetOffsetX = { -it }) — екран излази на леву страну. За pop анимацију, правци су огледални: екран улази са леве и излази на десну страну. За BottomNavigation користи се fadeIn/fadeOut без slide-а.

kotlin
NavHost(
    navController = navController,
    startDestination = "home",
    enterTransition = { slideInHorizontally(initialOffsetX = { it }) + fadeIn() },
    exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) + fadeOut() },
    popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) + fadeIn() },
    popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) + fadeOut() }
) { /* composable routes */ }

Прилагођене анимације се креирају кроз Compose Animation API: AnimatedContentTransitionScope пружа приступ димензијама контејнера, напретку анимације и direction. За shared element transition (један елемент глатко прелази на други екран) потребна је библиотека Accompanist Navigation Animation или прилагођена имплементација кроз sharedElement Modifier. Према Android Developers (2025), подразумевана slide анимација (улаз са десне, излаз на леву) користи се у 80% Android апликација са навигацијом.

Често постављана питања

Може ли се користити више NavHost-ова у једној Activity?

Технички да, али се не препоручује. Сваки NavHost ствара независан back stack, што нарушава јединствену навигацију. Изузетак — одвојене области, на пример NavHost за главни садржај и NavHost за BottomSheet са сопственом навигацијом.

По чему се разликује NavHost од Scaffold-а у Compose-у?

NavHost — контејнер навигације који пребацује екране. Scaffold — распоред целе странице (TopAppBar, BottomNavigation, FloatingActionButton). Обично се NavHost поставља унутар Scaffold.content. Scaffold не управља навигацијом, већ само обезбеђује слотове за UI компоненте.

Како пренети ViewModel између екрана кроз NavHost?

ViewModel се креира у оквиру NavBackStackEntry кроз viewModel(). За дељење ViewModel-а између екрана користите parentNavController: заједнички ViewModel повежите са родитељским entry. Алтернатива — DI (Hilt/Koin) са опсегом на NavGraph-у.

Зашто NavHost поново ствара composable при сваком прелазу?

То је нормално понашање — NavHost уклања composable из композиције при напуштању руте. За очување стања користите rememberSaveable за UI стање и ViewModel са SavedStateHandle за пословну логику.

Како додати обраду 404 (непозната рута) у NavHost?

Додајте последњу руту composable("404") и навигацију на њу при непознатом deep link-у. У NavHost-у не постоји catch-all рута — проверавајте руту у intent-handler-у Deep Link-а пре navigate(). Ако route није пронађен — navigate на 404.

Закључак

  • NavHost — composable контејнер Navigation Compose-а, који повезује NavController са графом рута и приказује тренутни екран
  • composable() региструје руту са route, аргументима (NavType), deep links и анимацијом
  • startDestination — почетна рута која се отвара при првом покретању NavHost-а
  • Аргументи се преносе кроз placeholder-е {param} са NavType за типизацију и defaultValue за опционе параметре
  • Угнежђени графови кроз navigation() омогућавају груписање рута по модулима са изолованим back stack-ом
  • Анимација прелаза се подешава кроз enterTransition/exitTransition уз коришћење Compose Animation API
  • NavHost аутоматски обрађује back press, чување стања и deep links без додатног кода

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође