NavHost är en composable-container som fungerar som startpunkt för navigeringsgrafen i Jetpack Compose. Den kopplar NavController till en uppsättning rutter och renderar den aktuella skärmen baserat på back stack-status. Enligt Android Developers (2025) är NavHost en obligatorisk komponent för alla Compose-appar med navigering. Inuti NavHost registreras composable-rutter med valfria argument, deep links och animering. Varje rutt är en vanlig composable-funktion som tar emot NavBackStackEntry med övergångsdata. NavHost hanterar automatiskt back press, tillståndssparning och återställning vid omkonfigurering.
Huvudpunkter
NavHost är en composable-funktion som tillhandahåller en container för att visa den aktuella navigeringsskärmen. NavHost tar emot NavController, startDestination och ruttgrafen byggd via Kotlin DSL. När den aktuella rutten ändras växlar NavHost den visade composablen med angiven animering.
NavHost fungerar som en skärmväxlare: den spårar den aktuella NavBackStackEntry från NavController och renderar motsvarande composable-block. Varje skärm är en oberoende composable-funktion som tar emot NavBackStackEntry med ruttargument. Alla skärmar finns i samma kompositionsträd, men NavHost visar bara en i taget och döljer de andra via animering.
Till skillnad från FragmentManager skapar NavHost inget Fragment för varje skärm. Hela livscykeln hanteras via CompositionLifecycle — composable-funktioner har inga onStart/onResume, så för sidoeffekter används LaunchedEffect och DisposableEffect. NavHost prenumererar automatiskt på NavController och återsammanställer UI när rutten ändras.
Enligt Google är NavHost ett stabilt API sedan Navigation 2.4.0. Från och med 2.8.0 stöder NavHost Type-Safe Navigation via Kotlin Serialization, vilket ersätter strängrutter med dataklasser. NavHost stöder även kapslade grafer, vilket möjliggör organisering av navigering per modul.
NavHost skapas med två obligatoriska parametrar: navController (NavHostController-instans) och startDestination (sträng för den första skärmens rutt). Den tredje parametern är builder-blocket där alla rutter registreras via composable(), navigation() och dialog().
@Composable
fun AppNavHost(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = "home"
) {
composable("home") { HomeScreen(navController) }
composable("settings") { SettingsScreen(navController) }
}
}
startDestination är rutten som öppnas när NavHost startas första gången. Om back stack är tom lägger NavHost automatiskt till startDestination i stacken. Vid omkonfigurering (skärmrotation) återställer NavHost den senaste rutten från savedState, inte startDestination.
För BottomNavigation är startDestination en av rutterna på den nedre panelen. Panelens övriga rutter läggs till som separata composable-poster. NavHost ska placeras inuti Scaffold.content — där appens huvudinnehåll visas. NavHost upptar hela tillgängliga höjden minus TopAppBar och BottomNavigation.
Funktionen composable(route, arguments, deepLinks, enterTransition, exitTransition, content) registrerar en rutt i NavHost-grafen. Parametern route är en sträng som beskriver sökvägen med valfria platshållare i formen {paramName}. Platshållaren ersätts med ett konkret värde vid navigering.
Content-blocket tar emot NavBackStackEntry från vilket argumenten extraheras. Composable-funktionen för skärmen renderas endast när NavControllers aktuella rutt matchar route. Vid obalans tas composablen bort från kompositionen, men dess tillstånd kan sparas via rememberSaveable eller ViewModel med 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)
}
Antalet composable-poster i NavHost kan vara vilket som helst — från några till hundratals. För stora appar delas rutterna upp per modul och kopplas via kapslade grafer. Varje composable kan ha egna inställningar för animering, deep links och argument.
Ruttargument definieras via parametern arguments: List<NamedNavArgument> i composable(). Varje argument anges via navArgument(name) { type; defaultValue }. NavType bestämmer argumenttypen: StringType, IntType, LongType, FloatType, BoolType, ParcelableType och ReferenceType.
| Ruttparameter | Exempel route | NavType |
|---|---|---|
| Sökväg (path) | "user/{id}" | NavType.IntType |
| Fråga (query) | "search?q={query}" | NavType.StringType |
| Valfri | "details/{id}?tab={tab}" | StringType + defaultValue="" |
| Parcelable | "checkout/{order}" | NavType.ParcelableType |
Argument extraheras från NavBackStackEntry via arguments?.getInt("id"). För obligatoriska argument kan defaultValue utelämnas — NavType använder null. För valfria argument är defaultValue obligatorisk, annars kastar navigeringen ett undantag när parametern saknas.
Från Navigation 2.8.0 rekommenderas Type-Safe Navigation: definiera en sealed class eller data class för rutter med Kotlin Serialization. Använd composable<RouteType> { backStackEntry -> } istället för strängroute. Detta eliminerar skrivfel i route och genererar automatiskt NavType för argument. För migrering, lägg till beroendet navigation-compose-typesafe och plugin-programmet Kotlin Serialization.
nested graphs — mekanism för att gruppera rutter i NavHost via funktionen navigation(route, startDestination). En kapslad graf har eget route-prefix och startDestination, och alla dess rutter är tillgängliga via prefixet. nested graphs används för modulär arkitektur, där varje feature-modul registrerar sin egen subgraf.
Fördelar med kapslade grafer: isolering av rutter inom modulen, enhetlig back stack för en grupp skärmar, möjlighet att navigera via prefix utan att avslöja intern struktur. Till exempel innehåller grafen "auth" rutterna "auth/login" och "auth/register". Navigering är möjlig både via full rutt och via prefix med omdirigering till 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 stöder vidarebefordran av argument på grafnivå: parametrar deklarerade i grafens route skickas till alla interna rutter. För att rensa en kapslad graf, använd popBackStack(route) — den tar bort alla interna poster. Kapslade grafer har ingen djupbegränsning, men för läsbarhet rekommenderas högst 3 nivåer.
NavHost stöder övergångsanimering mellan composable-rutter via parametrarna enterTransition, exitTransition, popEnterTransition och popExitTransition. Animeringar definieras en gång för NavHost och tillämpas på alla rutter, eller individuellt för varje composable. Som standard är animering inaktiverad.
Typisk konfiguration: enterTransition = slideInHorizontally(initialOffsetX = { it }) — skärmen kommer in från höger; exitTransition = slideOutHorizontally(targetOffsetX = { -it }) — skärmen åker ut till vänster. För pop-animering är riktningarna spegelvända: skärmen kommer in från vänster och åker ut till höger. För BottomNavigation används fadeIn/fadeOut utan 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 */ }
Anpassade animeringar skapas via Compose Animation API: AnimatedContentTransitionScope ger tillgång till containerns dimensioner, animeringsförlopp och direction. För shared element transition (ett element som smidigt övergår till en annan skärm) krävs biblioteket Accompanist Navigation Animation eller anpassad implementering via sharedElement Modifier. Enligt Android Developers (2025) används standard slide-animeringen (inkomst från höger, utgång till vänster) i 80% av Android-appar med navigering.
Vanliga frågor
Tekniskt ja, men rekommenderas inte. Varje NavHost skapar en oberoende back stack, vilket bryter den enhetliga navigeringen. Undantag — separata områden, till exempel NavHost för huvudinnehåll och NavHost för BottomSheet med egen navigering.
NavHost — navigeringscontainer som växlar skärmar. Scaffold — layout för hela sidan (TopAppBar, BottomNavigation, FloatingActionButton). Vanligtvis placeras NavHost inuti Scaffold.content. Scaffold hanterar inte navigering, utan tillhandahåller bara platshållare för UI-komponenter.
ViewModel skapas inom NavBackStackEntry via viewModel(). För att dela ViewModel mellan skärmar, använd parentNavController: koppla den delade ViewModel till den överordnade entry. Alternativ — DI (Hilt/Koin) med scope på NavGraph.
Detta är normalt beteende — NavHost tar bort composablen från kompositionen när rutten lämnas. För att bevara tillstånd, använd rememberSaveable för UI-tillstånd och ViewModel med SavedStateHandle för affärslogik.
Lägg till den sista rutten composable("404") och navigera till den vid okänd deep link. NavHost har ingen catch-all-rutt — kontrollera rutten i Deep Link intent-handler före navigate(). Om route inte hittas — navigera till 404.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också