NavHost — o que é, construção do grafo e rotas no Jetpack Compose

Autor: IT Sectr Publicado: 2026-06-30 Tempo de leitura: 7 min

NavHost é um contêiner composable que serve como ponto de entrada para o grafo de navegação no Jetpack Compose. Ele vincula um NavController a um conjunto de rotas e renderiza a tela atual com base no estado da pilha de retorno. Segundo Android Developers (2025), NavHost é um componente obrigatório para qualquer aplicativo Compose com navegação. Dentro do NavHost, rotas composable são registradas com argumentos opcionais, deep links e animações. Cada rota é uma função composable comum que recebe um NavBackStackEntry com dados de transição. O NavHost lida automaticamente com o botão de voltar, salvamento de estado e restauração na reconfiguração.

Principais Pontos

  • NavHost — um contêiner composable que vincula NavController a um grafo de rotas e renderiza a tela atual
  • composable() — uma função para registrar uma rota com caminho, argumentos, deep links e animações de transição
  • startDestination — a rota inicial aberta ao criar NavHost
  • Argumentos são definidos via navArgument com NavType para transferência de dados tipados entre telas
  • Animação é configurada global ou individualmente através dos parâmetros enterTransition, exitTransition

O que é NavHost no Jetpack Compose?

NavHost é uma função composable que fornece um contêiner para exibir a tela de navegação atual. NavHost recebe um NavController, startDestination e um grafo de rotas construído via Kotlin DSL. Quando a rota atual muda, NavHost alterna o composable exibido com a animação especificada.

NavHost funciona como um alternador de telas: ele rastreia o NavBackStackEntry atual do NavController e renderiza o bloco composable correspondente. Cada tela é uma função composable independente que recebe um NavBackStackEntry com argumentos de rota. Todas as telas existem em uma única árvore de composição, mas NavHost mostra apenas uma por vez, ocultando as outras através de animação.

Ao contrário do FragmentManager, NavHost não cria um Fragment para cada tela. Todo o ciclo de vida é gerenciado através do CompositionLifecycle — funções composable não têm onStart/onResume, então LaunchedEffect e DisposableEffect são usados para efeitos colaterais. NavHost se inscreve automaticamente no NavController e recompõe a UI quando a rota muda.

Segundo o Google, NavHost é uma API estável desde Navigation 2.4.0. A partir da 2.8.0, NavHost suporta navegação Type-Safe através do Kotlin Serialization, substituindo rotas de string por classes de dados. NavHost também suporta grafos aninhados, permitindo organização modular da navegação.

NavHost é criado com dois parâmetros obrigatórios: navController (uma instância de NavHostController) e startDestination (a string de rota da primeira tela). O terceiro parâmetro é um bloco construtor onde todas as rotas são registradas via composable(), navigation() e dialog().

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

startDestination é a rota que abre quando NavHost é iniciado pela primeira vez. Se a pilha de retorno estiver vazia, NavHost adiciona automaticamente startDestination à pilha. Na reconfiguração (rotação de tela), NavHost restaura a última rota de savedState, não startDestination.

Para BottomNavigation, startDestination é uma das rotas do painel inferior. As rotas restantes do painel são adicionadas como entradas composable separadas. NavHost deve ser colocado dentro de Scaffold.content — onde o conteúdo principal do aplicativo é exibido. NavHost ocupa toda a altura disponível menos TopAppBar e BottomNavigation.

Registro de rotas via composable

A função composable(route, arguments, deepLinks, enterTransition, exitTransition, content) registra uma rota no grafo do NavHost. O parâmetro route é uma string que descreve o caminho com placeholders opcionais na forma {paramName}. O placeholder é substituído por um valor real durante a navegação.

O bloco content do composable recebe um NavBackStackEntry do qual os argumentos são extraídos. A função composable da tela é renderizada apenas quando a rota atual do NavController corresponde à rota. Em caso de incompatibilidade, o composable é removido da composição, mas seu estado pode ser preservado através de rememberSaveable ou ViewModel com 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)
}

O número de entradas composable dentro do NavHost pode variar de algumas a centenas. Para aplicações grandes, as rotas são divididas em módulos e conectadas via grafos aninhados. Cada composable pode ter suas próprias configurações de animação, deep links e argumentos.

Argumentos e parâmetros de rota tipados

Os argumentos de rota são definidos através do parâmetro arguments: List<NamedNavArgument> em composable(). Cada argumento é definido via navArgument(name) { type; defaultValue }. NavType determina o tipo de argumento: StringType, IntType, LongType, FloatType, BoolType, ParcelableType e ReferenceType.

Parâmetro de rotaExemplo de rotaNavType
Caminho (path)"user/{id}"NavType.IntType
Consulta (query)"search?q={query}"NavType.StringType
Opcional"details/{id}?tab={tab}"StringType + defaultValue=""
Parcelable"checkout/{order}"NavType.ParcelableType

Os argumentos são extraídos de NavBackStackEntry via arguments?.getInt("id"). Para argumentos obrigatórios, defaultValue pode ser omitido — NavType usará null. Para argumentos opcionais, defaultValue deve ser definido, caso contrário a navegação lançará uma exceção se o parâmetro estiver ausente.

Desde Navigation 2.8.0, a navegação Type-Safe é recomendada: defina uma classe selada ou classe de dados para rotas com Kotlin Serialization. Em vez de uma rota de string, use composable<RouteType> { backStackEntry -> }. Isso elimina erros de digitação nas rotas e gera automaticamente NavType para argumentos. Para migrar, adicione a dependência navigation-compose-typesafe e o plugin Kotlin Serialization.

Grafos de navegação aninhados

nested graphs — um mecanismo para agrupar rotas dentro do NavHost usando a função navigation(route, startDestination). Um grafo aninhado tem seu próprio prefixo de rota e startDestination, e todas as suas rotas são acessíveis através do prefixo. Grafos aninhados são usados para arquitetura modular, onde cada módulo de funcionalidade registra seu próprio subgrafo.

Benefícios dos grafos aninhados: isolamento de rotas dentro de um módulo, uma pilha de retorno unificada para um grupo de telas e a capacidade de navegar por prefixo sem expor a estrutura interna. Por exemplo, o grafo "auth" contém "auth/login" e "auth/register". A navegação é possível tanto pela rota completa quanto por prefixo com redirecionamento para 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) }
    }
}

Grafos aninhados suportam passagem de argumentos no nível do grafo: parâmetros declarados na rota do grafo são passados para todas as rotas internas. Para limpar um grafo aninhado, use popBackStack(route) — removerá todas as entradas internas. Grafos aninhados não têm limite de profundidade, mas não mais que 3 níveis são recomendados para legibilidade.

Personalização de animações e transições

NavHost suporta animações de transição entre rotas composable através dos parâmetros enterTransition, exitTransition, popEnterTransition e popExitTransition. As animações são definidas uma vez para NavHost e se aplicam a todas as rotas, ou individualmente para cada composable. Por padrão, as animações estão desativadas.

Configuração típica: enterTransition = slideInHorizontally(initialOffsetX = { it }) — a tela desliza da direita; exitTransition = slideOutHorizontally(targetOffsetX = { -it }) — a tela desliza para a esquerda. Para animação pop, as direções são espelhadas: a tela desliza da esquerda e desliza para a direita. Para BottomNavigation, usa-se fadeIn/fadeOut sem deslizamento.

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

Animações personalizadas são criadas usando Compose Animation API: AnimatedContentTransitionScope fornece acesso às dimensões do contêiner, progresso da animação e direção. Para transições de elemento compartilhado (um elemento se movendo suavemente para outra tela), a biblioteca Accompanist Navigation Animation ou uma implementação personalizada via sharedElement Modifier é necessária. Segundo Android Developers (2025), a animação de deslizamento padrão (entrada pela direita, saída pela esquerda) é usada em 80% dos aplicativos Android com navegação.

Perguntas Frequentes

Pode-se usar vários NavHost em uma mesma Activity?

Tecnicamente sim, mas não é recomendado. Cada NavHost cria uma pilha de retorno independente, quebrando a navegação unificada. A exceção são áreas separadas, como um NavHost para o conteúdo principal e um NavHost para um BottomSheet com navegação própria.

Qual a diferença entre NavHost e Scaffold no Compose?

NavHost é um contêiner de navegação que alterna telas. Scaffold é o layout de toda a página (TopAppBar, BottomNavigation, FloatingActionButton). Normalmente, NavHost é colocado dentro de Scaffold.content. Scaffold não gerencia navegação, apenas fornece slots para componentes de UI.

Como compartilhar um ViewModel entre telas através do NavHost?

Um ViewModel é criado dentro de um NavBackStackEntry através de viewModel(). Para compartilhar um ViewModel entre telas, use parentNavController: vincule o ViewModel compartilhado à entrada pai. Uma alternativa é DI (Hilt/Koin) com escopo NavGraph.

Por que NavHost recria o composable a cada navegação?

Este é um comportamento normal — NavHost remove o composable da composição ao sair de uma rota. Para preservar o estado, use rememberSaveable para estado de UI e ViewModel com SavedStateHandle para lógica de negócios.

Como adicionar tratamento 404 (rota desconhecida) no NavHost?

Adicione uma rota final composable("404") e navegue para ela quando um deep link desconhecido for recebido. NavHost não tem uma rota catch-all — verifique a rota no manipulador de intent Deep Link antes de navigate(). Se a rota não for encontrada, navegue para 404.

Resumo

  • NavHost — um contêiner composable Navigation Compose que vincula NavController a um grafo de rotas e renderiza a tela atual
  • composable() registra uma rota com caminho, argumentos (NavType), deep links e animações
  • startDestination — a rota inicial aberta quando NavHost é iniciado pela primeira vez
  • Argumentos são passados através de placeholders {param} com NavType para tipagem e defaultValue para parâmetros opcionais
  • Grafos aninhados via navigation() permitem agrupar rotas por módulos com uma pilha de retorno isolada
  • Animação de transições é configurada através de enterTransition/exitTransition usando Compose Animation API
  • NavHost lida automaticamente com botão de voltar, salvamento de estado e deep links sem código adicional

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também