A navegação descreve a maneira como os usuários se movem pelo app. Eles interagem com elementos da interface, geralmente tocando ou clicando neles, e o app responde exibindo um novo conteúdo. Se o usuário quiser voltar ao conteúdo anterior, ele vai usar o gesto de volta ou tocar no botão de volta.
Como modelar o estado de navegação
Uma maneira conveniente de modelar esse comportamento é com uma pilha de conteúdo. À medida que o usuário navega para frente para um novo conteúdo, ele é empurrado para a parte de cima da pilha. Quando eles voltam para esse conteúdo, ele é retirado da pilha e o conteúdo anterior é exibido. Em termos de navegação, essa pilha geralmente é chamada de backstack porque representa o conteúdo que o usuário pode acessar novamente.

Criar uma backstack
Na navegação 3, a backstack não contém conteúdo. Em vez disso, ele contém referências ao conteúdo, conhecidas como chaves. As chaves podem ser de qualquer tipo, mas geralmente são classes de dados simples e serializáveis. Usar referências em vez de conteúdo tem as seguintes vantagens:
- É simples navegar pressionando teclas na backstack.
- Contanto que as chaves sejam serializáveis, a backstack pode ser salva no armazenamento persistente, permitindo que ela sobreviva a mudanças de configuração e à morte do processo. Isso é importante porque os usuários esperam sair do app, voltar a ele mais tarde e continuar de onde pararam com o mesmo conteúdo exibido. Consulte Salvar a backstack para mais informações.
Um conceito importante na API Navigation 3 é que você é o proprietário da backstack. A biblioteca:
- Espera que a backstack seja um
List<T>
com suporte a estado de snapshot, em queT
é o tipo dekeys
da backstack. Você pode usarAny
ou fornecer suas próprias chaves com tipos mais fortes. Quando você vê os termos "push" ou "pop", a implementação subjacente é adicionar ou remover itens do final de uma lista. - Observa a backstack e reflete o estado dela na interface usando um
NavDisplay
.
O exemplo a seguir mostra como criar chaves e uma backstack e modificar a backstack em resposta aos eventos de navegação do usuário:
// Define keys that will identify content data object ProductList data class ProductDetail(val id: String) @Composable fun MyApp() { // Create a back stack, specifying the key the app should start with val backStack = remember { mutableStateListOf<Any>(ProductList) } // Supply your back stack to a NavDisplay so it can reflect changes in the UI // ...more on this below... // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state backStack.add(ProductDetail(id = "ABC")) // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state backStack.removeLastOrNull() }
Resolver chaves para conteúdo
O conteúdo é modelado na Navigation 3 usando NavEntry
, que é uma classe que contém
uma função combinável. Ele representa um destino, um único conteúdo
que o usuário pode navegar e voltar.
Um NavEntry
também pode conter metadados, ou seja, informações sobre o conteúdo. Esses
metadados podem ser lidos por objetos de contêiner, como NavDisplay
, para ajudar a
decidir como exibir o conteúdo do NavEntry
. Por exemplo, os metadados podem ser
usados para substituir as animações padrão de um NavEntry
específico. NavEntry
metadata
é um mapa de chaves String
para valores Any
, fornecendo armazenamento de dados
versátil.
Para converter um key
em um NavEntry
, crie um entryProvider
. Essa é uma
função que aceita um key
e retorna um NavEntry
para esse key
. Ele geralmente é
definido como um parâmetro lambda ao criar uma NavDisplay
.
Há duas maneiras de criar um entryProvider
: criando uma função
lambda diretamente ou usando a DSL entryProvider
.
Criar uma função entryProvider
diretamente
Normalmente, você cria uma função entryProvider
usando uma instrução when
, com
uma ramificação para cada uma das chaves.
entryProvider = { key -> when (key) { is ProductList -> NavEntry(key) { Text("Product List") } is ProductDetail -> NavEntry( key, metadata = mapOf("extraDataKey" to "extraDataValue") ) { Text("Product ${key.id} ") } else -> { NavEntry(Unit) { Text(text = "Invalid Key: $it") } } } }
Usar a DSL entryProvider
A DSL entryProvider
pode simplificar sua função lambda evitando a necessidade
de testar cada um dos tipos de chave e construir um NavEntry
para cada uma delas.
Para isso, use a função do builder entryProvider
. Ele também inclui o comportamento padrão
de substituto (gerando um erro) se a chave não for encontrada.
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
Observe o seguinte no snippet:
entry
é usado para definir umNavEntry
com o tipo e o conteúdo combinável especificados.entry
aceita um parâmetrometadata
para definirNavEntry.metadata
Mostrar a backstack
A backstack representa o estado de navegação do app. Sempre que a backstack
mudar, a interface do app vai refletir o novo estado da backstack. No Navigation 3, um
NavDisplay
observa a backstack e atualiza a interface de acordo com ela. Crie
com os seguintes parâmetros:
- Sua backstack: precisa ser do tipo
SnapshotStateList<T>
, em queT
é o tipo das chaves da backstack. Ele é umList
observável para que acione a recomposição deNavDisplay
quando ele mudar. - Um
entryProvider
para converter as chaves da backstack emNavEntry
s. - Opcionalmente, forneça uma lambda para o parâmetro
onBack
. Isso é chamado quando o usuário aciona um evento de retorno.
O exemplo a seguir mostra como criar uma NavDisplay
.
data object Home data class Product(val id: String) @Composable fun NavExample() { val backStack = remember { mutableStateListOf<Any>(Home) } NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = { key -> when (key) { is Home -> NavEntry(key) { ContentGreen("Welcome to Nav3") { Button(onClick = { backStack.add(Product("123")) }) { Text("Click to navigate") } } } is Product -> NavEntry(key) { ContentBlue("Product ${key.id} ") } else -> NavEntry(Unit) { Text("Unknown route") } } } ) }
Por padrão, a NavDisplay
mostra a NavEntry
mais alta na backstack em um
layout de painel único. A gravação a seguir mostra o app em execução:

NavDisplay
com dois
destinos.Para resumir
O diagrama a seguir mostra como os dados fluem entre os vários objetos na Navegação 3:

Os eventos de navegação iniciam mudanças. As chaves são adicionadas ou removidas da backstack em resposta às interações do usuário.
A mudança no estado da backstack aciona a recuperação de conteúdo. O
NavDisplay
(um elemento combinável que renderiza uma backstack) observa a backstack. Na configuração padrão, ele mostra a entrada da backstack mais alta em um único layout de painel. Quando a chave superior na backstack muda, oNavDisplay
usa essa chave para solicitar o conteúdo correspondente do provedor de entrada.O provedor de entrada fornece conteúdo. O provedor de entrada é uma função que resolve uma chave para um
NavEntry
. Ao receber uma chave doNavDisplay
, o provedor de entrada fornece oNavEntry
associado, que contém a chave e o conteúdo.O conteúdo é exibido. O
NavDisplay
recebe oNavEntry
e mostra o conteúdo.