NavHost — cos'è, costruzione del grafo e route in Jetpack Compose

Autore: IT Sectr Pubblicato: 2026-06-30 Tempo di lettura: 7 min

NavHost è un contenitore composable che funge da punto di ingresso per il grafo di navigazione in Jetpack Compose. Collega un NavController a un insieme di route e visualizza la schermata corrente in base allo stato della pila di navigazione. Secondo Android Developers (2025), NavHost è un componente obbligatorio per qualsiasi applicazione Compose con navigazione. All'interno di NavHost, le route composable vengono registrate con argomenti opzionali, deep link e animazioni. Ogni route è una normale funzione composable che riceve un NavBackStackEntry con i dati di transizione. NavHost gestisce automaticamente il pulsante indietro, il salvataggio dello stato e il ripristino in caso di riconfigurazione.

Punti Chiave

  • NavHost — un contenitore composable che collega NavController a un grafo di route e visualizza la schermata corrente
  • composable() — una funzione per registrare una route con percorso, argomenti, deep link e animazioni di transizione
  • startDestination — la route iniziale aperta alla creazione di NavHost
  • Argomenti sono definiti tramite navArgument con NavType per il trasferimento di dati tipizzati tra schermate
  • Animazione è configurata globalmente o individualmente tramite i parametri enterTransition, exitTransition

Cos'è NavHost in Jetpack Compose?

NavHost è una funzione composable che fornisce un contenitore per visualizzare la schermata di navigazione corrente. NavHost accetta un NavController, startDestination e un grafo di route costruito tramite Kotlin DSL. Quando la route corrente cambia, NavHost commuta il composable visualizzato con l'animazione specificata.

NavHost funge da commutatore di schermate: tiene traccia del NavBackStackEntry corrente da NavController e visualizza il blocco composable corrispondente. Ogni schermata è una funzione composable indipendente che riceve un NavBackStackEntry con gli argomenti della route. Tutte le schermate esistono in un singolo albero di composizione, ma NavHost ne mostra solo una alla volta, nascondendo le altre tramite animazione.

A differenza di FragmentManager, NavHost non crea un Fragment per ogni schermata. L'intero ciclo di vita è gestito tramite CompositionLifecycle — le funzioni composable non hanno onStart/onResume, quindi LaunchedEffect e DisposableEffect vengono utilizzati per gli effetti collaterali. NavHost si sottoscrive automaticamente a NavController e ricompone l'UI quando la route cambia.

Secondo Google, NavHost è un'API stabile da Navigation 2.4.0. A partire da 2.8.0, NavHost supporta la navigazione Type-Safe tramite Kotlin Serialization, sostituendo le route stringa con classi di dati. NavHost supporta anche grafici annidati, consentendo un'organizzazione modulare della navigazione.

NavHost viene creato con due parametri obbligatori: navController (un'istanza di NavHostController) e startDestination (la stringa di route della prima schermata). Il terzo parametro è un blocco costruttore in cui tutte le route vengono registrate tramite composable(), navigation() e dialog().

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

startDestination è la route che si apre al primo avvio di NavHost. Se la pila di navigazione è vuota, NavHost aggiunge automaticamente startDestination alla pila. In caso di riconfigurazione (rotazione dello schermo), NavHost ripristina l'ultima route da savedState, non startDestination.

Per BottomNavigation, startDestination è una delle route del pannello inferiore. Le restanti route del pannello vengono aggiunte come voci composable separate. NavHost dovrebbe essere posizionato all'interno di Scaffold.content — dove viene visualizzato il contenuto principale dell'applicazione. NavHost occupa tutta l'altezza disponibile meno TopAppBar e BottomNavigation.

Registrazione delle route tramite composable

La funzione composable(route, arguments, deepLinks, enterTransition, exitTransition, content) registra una route nel grafo di NavHost. Il parametro route è una stringa che descrive il percorso con segnaposto opzionali nella forma {paramName}. Il segnaposto viene sostituito con un valore effettivo durante la navigazione.

Il blocco content di composable riceve un NavBackStackEntry da cui vengono estratti gli argomenti. La funzione composable della schermata viene visualizzata solo quando la route corrente di NavController corrisponde alla route. In caso di mancata corrispondenza, il composable viene rimosso dalla composizione, ma il suo stato può essere preservato tramite rememberSaveable o ViewModel con 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)
}

Il numero di voci composable all'interno di NavHost può variare da poche a centinaia. Per applicazioni grandi, le route vengono suddivise in moduli e collegate tramite grafici annidati. Ogni composable può avere le proprie impostazioni di animazione, deep link e argomenti.

Argomenti e parametri di route tipizzati

Gli argomenti di route sono definiti tramite il parametro arguments: List<NamedNavArgument> in composable(). Ogni argomento è definito tramite navArgument(name) { type; defaultValue }. NavType determina il tipo di argomento: StringType, IntType, LongType, FloatType, BoolType, ParcelableType e ReferenceType.

Parametro di routeEsempio di routeNavType
Percorso (path)"user/{id}"NavType.IntType
Query"search?q={query}"NavType.StringType
Opzionale"details/{id}?tab={tab}"StringType + defaultValue=""
Parcelable"checkout/{order}"NavType.ParcelableType

Gli argomenti vengono estratti da NavBackStackEntry tramite arguments?.getInt("id"). Per gli argomenti obbligatori, defaultValue può essere omesso — NavType userà null. Per gli argomenti opzionali, defaultValue deve essere impostato, altrimenti la navigazione genererà un'eccezione se il parametro è assente.

Da Navigation 2.8.0, si raccomanda la navigazione Type-Safe: definire una classe sealed o una classe di dati per le route con Kotlin Serialization. Invece di una route stringa, utilizzare composable<RouteType> { backStackEntry -> }. Questo elimina gli errori di digitazione nelle route e genera automaticamente NavType per gli argomenti. Per migrare, aggiungere la dipendenza navigation-compose-typesafe e il plugin Kotlin Serialization.

Grafici di navigazione annidati

nested graphs — un meccanismo per raggruppare le route all'interno di NavHost utilizzando la funzione navigation(route, startDestination). Un grafico annidato ha un proprio prefisso di route e startDestination, e tutte le sue route sono accessibili tramite il prefisso. I grafici annidati vengono utilizzati per architetture modulari, dove ogni modulo di funzionalità registra il proprio sottografico.

Vantaggi dei grafici annidati: isolamento delle route all'interno di un modulo, una pila di navigazione unificata per un gruppo di schermate e la possibilità di navigare per prefisso senza esporre la struttura interna. Ad esempio, il grafo "auth" contiene "auth/login" e "auth/register". La navigazione è possibile sia tramite la route completa che tramite prefisso con reindirizzamento a 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) }
    }
}

I grafici annidati supportano il passaggio di argomenti a livello di grafico: i parametri dichiarati nella route del grafico vengono passati a tutte le route interne. Per cancellare un grafico annidato, utilizzare popBackStack(route) — rimuoverà tutte le voci interne. I grafici annidati non hanno limiti di profondità, ma si raccomanda non più di 3 livelli per la leggibilità.

Personalizzazione di animazioni e transizioni

NavHost supporta animazioni di transizione tra route composable tramite i parametri enterTransition, exitTransition, popEnterTransition e popExitTransition. Le animazioni vengono impostate una volta per NavHost e si applicano a tutte le route, oppure individualmente per ogni composable. Per impostazione predefinita, le animazioni sono disabilitate.

Configurazione tipica: enterTransition = slideInHorizontally(initialOffsetX = { it }) — la schermata scorre da destra; exitTransition = slideOutHorizontally(targetOffsetX = { -it }) — la schermata scorre verso sinistra. Per l'animazione pop, le direzioni sono invertite: la schermata scorre da sinistra e scorre verso destra. Per BottomNavigation, viene utilizzato fadeIn/fadeOut senza scorrimento.

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 */ }

Le animazioni personalizzate vengono create utilizzando Compose Animation API: AnimatedContentTransitionScope fornisce accesso alle dimensioni del contenitore, al progresso dell'animazione e alla direzione. Per le transizioni di elementi condivisi (un elemento che si sposta senza soluzione di continuità su un'altra schermata), è necessaria la libreria Accompanist Navigation Animation o un'implementazione personalizzata tramite sharedElement Modifier. Secondo Android Developers (2025), l'animazione di scorrimento predefinita (ingresso da destra, uscita a sinistra) viene utilizzata nell'80% delle applicazioni Android con navigazione.

Domande Frequenti

Si possono usare più NavHost in una stessa Activity?

Tecnicamente sì, ma non è raccomandato. Ogni NavHost crea una pila di navigazione indipendente, rompendo la navigazione unificata. L'eccezione sono aree separate, come un NavHost per il contenuto principale e un NavHost per un BottomSheet con navigazione propria.

Qual è la differenza tra NavHost e Scaffold in Compose?

NavHost è un contenitore di navigazione che commuta le schermate. Scaffold è il layout dell'intera pagina (TopAppBar, BottomNavigation, FloatingActionButton). Tipicamente, NavHost è posizionato all'interno di Scaffold.content. Scaffold non gestisce la navigazione, fornisce solo slot per i componenti UI.

Come condividere un ViewModel tra schermate tramite NavHost?

Un ViewModel viene creato all'interno di un NavBackStackEntry tramite viewModel(). Per condividere un ViewModel tra schermate, utilizzare parentNavController: associare il ViewModel condiviso alla voce padre. Un'alternativa è DI (Hilt/Koin) con ambito NavGraph.

Perché NavHost ricrea il composable ad ogni navigazione?

Questo è un comportamento normale — NavHost rimuove il composable dalla composizione quando si lascia una route. Per preservare lo stato, utilizzare rememberSaveable per lo stato dell'UI e ViewModel con SavedStateHandle per la logica di business.

Come aggiungere la gestione 404 (route sconosciuta) in NavHost?

Aggiungere una route finale composable("404") e navigare verso di essa quando viene ricevuto un deep link sconosciuto. NavHost non ha una route catch-all — verificare la route nel gestore intent Deep Link prima di navigate(). Se la route non viene trovata, navigare verso 404.

Riepilogo

  • NavHost — un contenitore composable Navigation Compose che collega NavController a un grafo di route e visualizza la schermata corrente
  • composable() registra una route con percorso, argomenti (NavType), deep link e animazioni
  • startDestination — la route iniziale aperta al primo avvio di NavHost
  • Argomenti vengono passati tramite segnaposto {param} con NavType per la tipizzazione e defaultValue per parametri opzionali
  • Grafici annidati tramite navigation() consentono di raggruppare le route per moduli con una pila di navigazione isolata
  • Animazione delle transizioni è configurata tramite enterTransition/exitTransition utilizzando Compose Animation API
  • NavHost gestisce automaticamente il pulsante indietro, il salvataggio dello stato e i deep link senza codice aggiuntivo

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche