NavHost је composable контејнер који служи као улазна тачка за граф навигације у Jetpack Compose-у. Он повезује NavController са скупом рута и приказује тренутни екран у зависности од стања back stack-а. Према Android Developers (2025), NavHost је обавезна компонента за сваку Compose апликацију са навигацијом. Унутар NavHost-а региструју се composable руте са опционим аргументима, deep links и анимацијом. Свака рута је обична composable функција која прима NavBackStackEntry са подацима прелаза. NavHost аутоматски обрађује back press, чување стања и враћање при реконфигурацији.
Главне тачке
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().
@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(route, arguments, deepLinks, enterTransition, exitTransition, content) региструје руту у графу NavHost-а. Параметар route је стринг који описује путању са опционим placeholder-има облика {paramName}. Placeholder се замењује конкретном вредношћу при навигацији.
Content блок прима NavBackStackEntry из којег се извлаче аргументи. Composable функција екрана се приказује само када тренутна рута NavController-а одговара route. При неусаглашености, composable се уклања из композиције, али његово стање може бити сачувано кроз rememberSaveable или ViewModel са SavedStateHandle.
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.
| Параметар руте | Пример route | NavType |
|---|---|---|
| Путања (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.
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-а.
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 ствара независан back stack, што нарушава јединствену навигацију. Изузетак — одвојене области, на пример NavHost за главни садржај и NavHost за BottomSheet са сопственом навигацијом.
NavHost — контејнер навигације који пребацује екране. Scaffold — распоред целе странице (TopAppBar, BottomNavigation, FloatingActionButton). Обично се NavHost поставља унутар Scaffold.content. Scaffold не управља навигацијом, већ само обезбеђује слотове за UI компоненте.
ViewModel се креира у оквиру NavBackStackEntry кроз viewModel(). За дељење ViewModel-а између екрана користите parentNavController: заједнички ViewModel повежите са родитељским entry. Алтернатива — DI (Hilt/Koin) са опсегом на NavGraph-у.
То је нормално понашање — NavHost уклања composable из композиције при напуштању руте. За очување стања користите rememberSaveable за UI стање и ViewModel са SavedStateHandle за пословну логику.
Додајте последњу руту composable("404") и навигацију на њу при непознатом deep link-у. У NavHost-у не постоји catch-all рута — проверавајте руту у intent-handler-у Deep Link-а пре navigate(). Ако route није пронађен — navigate на 404.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође