O que é Navigation 3 Compose no Android?

Resposta rápida: Navigation 3 (ou Navigation 3 Compose) é a biblioteca de navegação do AndroidX feita para apps Android 100% Compose. Destinos são tipos serializáveis (@Serializable), a back stack é estado da UI com rememberNavBackStack, e a UI é renderizada pelo NavDisplay + entryProvider. Em 2026, use Navigation 3 em apps novos totalmente Compose; mantenha o Navigation Compose clássico em apps estáveis ou com Fragments. As duas bibliotecas coexistem — a migração não é obrigatória.

Você buscouResposta direta
Navigation 3Nova API AndroidX de navegação Compose-first
Navigation 3 ComposeMesma biblioteca, usada com Jetpack Compose
Navigation 3 AndroidDestinos tipados + NavDisplay no app Android
Vale migrar agora?Sim em app novo Compose; não é urgente em legado estável

Se você desenvolve Android com Compose, 2026 tornou o Navigation 3 uma opção real de arquitetura: navegação como estado da UI, back stack tipada, overlays e Predictive Back com menos gambiarra. Este guia cobre o que é, quando usar, dependências, fluxo idiomático em Kotlin e a comparação com o Navigation Compose tradicional.

Para base do ecossistema, revise também o guia de Jetpack Compose, o tutorial de Compose para iniciantes, Kotlin para Android, o guia clássico de Navigation Compose com NavHost e NavController e App Links / deep links.

CritérioNavigation 3Navigation Compose (clássico)
Modelo de destinosChaves tipadas serializáveis (@Serializable)Rotas em string ou tipos com NavType
Back stackEstado Compose explícito (rememberNavBackStack)Controlada pelo NavController
API de renderizaçãoNavDisplay + entryProviderNavHost + composable {}
Overlays e resultadosCidadãos de primeira classe na pilhaExigem APIs extras e mais boilerplate
Predictive backIntegração mais diretaSuportado, com mais configuração
Maturidade em produçãoMais novo (adoção crescente em 2026)Estável e amplamente adotado
Melhor paraApps novos, 100% Compose, estado tipadoApps legados, migração gradual, material maduro

O que é o Navigation 3?

O Navigation 3 é a biblioteca de navegação do AndroidX com abordagem Compose-first — é isso que as buscas por navigation 3, navigation 3 compose e navigation 3 android normalmente querem dizer. Em vez de herdar a mentalidade de Fragments, ela trata telas, overlays e o fluxo de ida/volta como estado serializável.

Na prática, isso significa algumas vantagens importantes:

  • chaves de navegação tipadas;
  • back stack controlada diretamente pelo seu estado;
  • integração natural com Compose;
  • suporte melhor para cenários modernos, como predictive back;
  • base mais limpa para animações, overlays e resultados entre destinos.

Se você já comparou paradigmas de UI moderna em artigos como Jetpack Compose vs XML, vai perceber que o Navigation 3 segue a mesma filosofia: menos acoplamento com infra antiga e mais foco em estado declarativo.

Por que o Navigation 3 importa em 2026?

Durante muito tempo, muita gente usou o Navigation Compose tradicional e resolveu o problema. E tudo bem: ele continua útil. O ponto é que o Navigation 3 tenta corrigir algumas dores recorrentes em apps totalmente declarativos:

  1. Back stack mais explícita — você manipula uma estrutura de navegação clara, em vez de depender de abstrações mais opacas.
  2. Melhor alinhamento com serialização — as chaves são tipos reais, não apenas strings e rotas improvisadas.
  3. Mais controle para experiências modernas — overlays, resultados entre telas e transições ficam mais naturais.
  4. Arquitetura mais previsível — navegação vira parte do estado da aplicação, o que combina com MVI, MVVM e fluxos reativos.

Se o seu time já trabalha com coroutines, Flow e telas orientadas a estado, a curva de adoção é muito mais tranquila.

Dependências do projeto

Um setup inicial pode começar assim:

// build.gradle.kts
plugins {
    id("com.android.application")
    kotlin("android")
    kotlin("plugin.serialization")
}

android {
    namespace = "br.dev.exemplo"
    compileSdk = 36

    defaultConfig {
        applicationId = "br.dev.exemplo"
        minSdk = 24
        targetSdk = 36
        versionCode = 1
        versionName = "1.0"
    }

    buildFeatures {
        compose = true
    }
}

dependencies {
    implementation("androidx.navigation3:navigation3-runtime:1.1.1")
    implementation("androidx.navigation3:navigation3-ui:1.1.1")
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
}

A parte do kotlin("plugin.serialization") é importante porque as chaves de navegação normalmente são serializáveis. Se você ainda não domina esse recurso, vale ler nosso glossário sobre serialization e o post sobre Kotlin Multiplatform, já que a modelagem serializável aparece em vários contextos modernos do ecossistema.

Modelando destinos tipados

Uma das ideias mais legais do Navigation 3 é parar de navegar por strings mágicas. Em vez disso, você define tipos:

import kotlinx.serialization.Serializable

@Serializable
object Home

@Serializable
data class DetalheArtigo(val slug: String)

@Serializable
object Favoritos

@Serializable
data class Perfil(val userId: String)

Isso já melhora a manutenção do projeto. Quando você muda um destino, o compilador passa a ajudar. É o mesmo ganho de segurança que a gente vê quando troca lógica frágil por sealed classes ou adota null safety.

Primeiro fluxo com rememberNavBackStack

Agora vamos montar uma navegação simples entre home e detalhe:

import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.ui.NavDisplay
import androidx.navigation3.ui.entryProvider
import androidx.navigation3.ui.entry

@Composable
fun AppNavigation() {
    val backStack = rememberNavBackStack(Home)

    NavDisplay(
        backStack = backStack,
        entryProvider = entryProvider {
            entry<Home> {
                HomeScreen(
                    onAbrirArtigo = { slug ->
                        backStack.add(DetalheArtigo(slug))
                    },
                    onAbrirFavoritos = {
                        backStack.add(Favoritos)
                    }
                )
            }

            entry<DetalheArtigo> { destino ->
                DetalheArtigoScreen(
                    slug = destino.slug,
                    onVoltar = { backStack.removeLastOrNull() }
                )
            }

            entry<Favoritos> {
                FavoritosScreen(
                    onVoltar = { backStack.removeLastOrNull() }
                )
            }
        }
    )
}

Perceba o padrão: a sua pilha é um estado Compose, e a UI renderiza conforme esse estado. Isso conversa muito bem com arquiteturas que já usam MVVM ou fluxos baseados em reducer.

Exemplo de telas reais

Vamos imaginar um app de conteúdo técnico em Kotlin:

@Composable
fun HomeScreen(
    onAbrirArtigo: (String) -> Unit,
    onAbrirFavoritos: () -> Unit,
) {
    Scaffold(
        topBar = {
            TopAppBar(title = { Text("Kotlin Brasil App") })
        }
    ) { padding ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(padding)
                .padding(24.dp),
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            Button(onClick = { onAbrirArtigo("navigation-3-compose-android-2026") }) {
                Text("Abrir artigo sobre Navigation 3")
            }

            OutlinedButton(onClick = onAbrirFavoritos) {
                Text("Ver favoritos")
            }
        }
    }
}

@Composable
fun DetalheArtigoScreen(
    slug: String,
    onVoltar: () -> Unit,
) {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("Detalhe do artigo") },
                navigationIcon = {
                    TextButton(onClick = onVoltar) {
                        Text("Voltar")
                    }
                }
            )
        }
    ) { padding ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(padding)
                .padding(24.dp)
        ) {
            Text("Slug recebido: $slug")
        }
    }
}

Essa abordagem evita muito boilerplate. E como a chave DetalheArtigo já carrega o slug, você reduz o risco de navegar com argumentos inconsistentes.

Quando o Navigation 3 é melhor que o Navigation Compose tradicional?

A resposta honesta é: depende do momento do projeto.

Vale mais a pena quando:

  • o app é 100% Compose;
  • o time quer navegação realmente orientada a estado;
  • há preocupação com tipagem forte e serialização;
  • o roadmap inclui transições mais sofisticadas, overlays ou predictive back;
  • o projeto ainda não carregou legado forte de Fragments.

Talvez não valha migrar agora quando:

  • o app atual já está estável com Navigation Compose tradicional;
  • a equipe tem pouco tempo para revisar arquitetura;
  • a navegação do produto é simples e não sofre dores reais;
  • grande parte do fluxo ainda depende de Fragment ou XML.

Esse tipo de análise é parecido com a discussão de Kotlin vs Java em 2026: a melhor tecnologia não existe no vácuo, e sim dentro do custo de adoção do seu time. Para aprofundar o lado clássico, leia o guia de Navigation Compose com NavHost e NavController.

Overlays, resultados e experiências modernas

Um dos pontos que mais chamam atenção no Navigation 3 é a evolução para cenas e overlays. Isso abre espaço para lidar melhor com dialogs, folhas modais e fluxos que devolvem resultado para a tela anterior.

Imagine uma tela de perfil que abre um seletor de tema como overlay. Em vez de improvisar estados espalhados pela UI, você consegue tratar isso como parte da navegação.

Um modelo simplificado seria algo assim:

@Serializable
data class EditorPerfil(val userId: String)

@Serializable
object SeletorTema

Com isso, você consegue representar na pilha algo como:

  • Home
  • Perfil("42")
  • SeletorTema

Essa clareza ajuda muito em debug, analytics e restauração de estado. Se você já se interessa por instrumentação, aproveite também nosso conteúdo sobre observabilidade em Kotlin e Tracy para observabilidade de IA, porque navegação bem modelada também melhora rastreabilidade de eventos.

Predictive back e UX Android moderna

O Android moderno está cada vez mais orientado a gestos, e o predictive back ganhou relevância real em apps que se preocupam com experiência refinada. O Navigation 3 conversa melhor com esse cenário porque sua pilha de navegação é explícita.

Na prática, isso traz benefícios como:

  • comportamento de retorno mais previsível;
  • integração mais clara com o ciclo de navegação;
  • menos gambiarra para sincronizar estado de tela e gesto do sistema.

Esse detalhe importa bastante em apps com múltiplos níveis de profundidade, filtros, painéis laterais e telas com overlays.

Boas práticas para adotar Navigation 3

Se você resolver experimentar em produção, siga estas recomendações:

1. Comece por um fluxo isolado

Não tente reescrever o app inteiro de uma vez. Pilote numa feature nova, como onboarding, área autenticada ou detalhes de conteúdo.

2. Modele destinos com tipos pequenos

Evite colocar objetos gigantes na chave. Prefira IDs, slugs ou parâmetros mínimos.

3. Deixe a regra de negócio fora da navegação

Navegação deve descrever fluxo de tela, não carregar lógica de domínio. Para isso, use ViewModels, casos de uso e camadas que você já conhece de Clean Architecture em Kotlin.

4. Teste a serialização

Se a chave for serializável, valide cenários de restauração de processo e retomada de estado.

5. Observe o custo de migração

Em apps legados, às vezes o maior ganho está em melhorar a arquitetura ao redor primeiro, e só depois trocar a navegação.

Exemplo de integração com ViewModel

Um padrão comum é deixar o ViewModel emitir eventos que alteram a pilha:

class HomeViewModel : ViewModel() {
    private val _eventos = MutableSharedFlow<HomeEvent>()
    val eventos = _eventos.asSharedFlow()

    fun abrirArtigo(slug: String) {
        viewModelScope.launch {
            _eventos.emit(HomeEvent.AbrirArtigo(slug))
        }
    }
}

sealed interface HomeEvent {
    data class AbrirArtigo(val slug: String) : HomeEvent
}

E na tela:

LaunchedEffect(Unit) {
    viewModel.eventos.collect { evento ->
        when (evento) {
            is HomeEvent.AbrirArtigo -> backStack.add(DetalheArtigo(evento.slug))
        }
    }
}

Esse estilo mantém a UI declarativa e ainda preserva uma fronteira clara entre intenção do usuário e mudança de navegação.

Vale a pena estudar Navigation 3 agora?

Sim, especialmente se você trabalha com Android moderno, Compose e arquitetura orientada a estado. Mesmo que seu time ainda não migre imediatamente, entender o Navigation 3 ajuda a enxergar melhor para onde o ecossistema Jetpack está caminhando.

Para quem está começando um app novo em 2026, ele já é uma alternativa muito plausível. Para apps maduros, a adoção precisa ser estratégica, mas faz sentido acompanhar desde já.

No fim, o maior valor do Navigation 3 não é apenas “navegar entre telas”. É permitir que a navegação deixe de ser uma camada especial e passe a ser tratada como parte legítima do estado da sua interface.

Checklist rápido: começar com Navigation 3 Compose

  1. App (ou feature) 100% Compose, sem Fragment no fluxo-alvo.
  2. Plugin kotlin("plugin.serialization") + artefatos navigation3-runtime / navigation3-ui.
  3. Destinos como @Serializable object / data class (IDs/slugs, não objetos gigantes).
  4. rememberNavBackStack(Home) + NavDisplay com entryProvider / entry<T>.
  5. Voltar via backStack.removeLastOrNull() alinhado ao Predictive Back.
  6. Testar restauração de processo e deep links com App Links.

Perguntas Frequentes

O que é Navigation 3 Compose?

É o nome comum da Navigation 3 usada com Jetpack Compose no Android: destinos tipados, back stack como estado (rememberNavBackStack) e renderização com NavDisplay. Não é um produto separado do Navigation 3 — é o mesmo pacote AndroidX no contexto Compose.

Não. As duas abordagens podem coexistir — inclusive no mesmo app durante a migração. O Navigation 3 é mais alinhado a Compose-first e estado tipado; a migração depende do contexto. O guia de Navigation Compose clássico continua válido para a maioria dos apps em produção.

É onde o ROI é maior. Em apps Android novos e 100% Compose, comece com Navigation 3. Em apps maduros com Navigation Compose estável, migre por feature isolada (onboarding, detalhe, área autenticada) em vez de reescrever tudo de uma vez.

Preciso usar serialização com Navigation 3?

Na maioria dos exemplos modernos, sim. O padrão é modelar destinos com tipos serializáveis, o que melhora restauração de estado e segurança de navegação. Veja também o glossário de serialization.

O foco principal é Compose. Em apps fortemente baseados em Fragment, a adoção tende a fazer menos sentido, principalmente se a base atual já estiver estável.

Vale usar Navigation 3 em app novo?

Para apps novos, 100% Compose e com equipe confortável com arquitetura declarativa, sim. É onde a biblioteca entrega o maior benefício.

Como o Navigation 3 se relaciona com Predictive Back?

A pilha explícita facilita alinhar o gesto de voltar do sistema à UX real. Para o setup de plataforma (enableOnBackInvokedCallback, BackHandler e animações), use o guia de Predictive Back no Android com Compose.

Como estudar mais navegação e arquitetura Android com Kotlin?

Além da documentação oficial, aprofunde em Jetpack Compose, MVVM com Kotlin, coroutines e Flow. Para quem também desenvolve multiplataforma, compare com outras stacks — como Rust com frameworks como Dioxus aborda UI declarativa e navegação tipada.