A navegação descreve a forma como os usuários se movem pelo app. Eles interagem com elementos da interface, geralmente tocando ou clicando neles, e o app responde mostrando um novo conteúdo. Se o usuário quiser voltar ao conteúdo anterior, ele usa o gesto de volta ou toca no botão "Voltar".
Modelagem do 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 até um novo conteúdo, ele é colocado no topo da pilha. Quando eles voltam desse conteúdo, ele é removido da pilha e o conteúdo anterior é exibido. Em termos de navegação, essa pilha geralmente é chamada de pilha de retorno porque representa o conteúdo a que o usuário pode voltar.

Criar uma pilha de retorno
Na navegação 3, a pilha de retorno não contém conteúdo. Em vez disso, ele contém referências a 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 os seguintes benefícios:
- É simples navegar pressionando as chaves na backstack.
- Desde que as chaves sejam serializáveis, a pilha de retorno pode ser salva no armazenamento permanente, 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 depois e continuar de onde pararam com o mesmo conteúdo sendo mostrado. Consulte Salvar sua pilha de retorno para mais informações.
Um conceito importante da API Navigation 3 é que você é o proprietário da backstack. A biblioteca:
- Espera que sua pilha de retorno seja um
List<T>
com estado de snapshot, em queT
é o tipo dokeys
da pilha de retorno. Você pode usarAny
ou fornecer suas próprias chaves com tipagem mais forte. Quando você vê os termos "push" ou "pop", a implementação subjacente é adicionar ou remover itens do final de uma lista. - Observa a pilha de retorno e reflete o estado dela na interface usando um
NavDisplay
.
O exemplo a seguir mostra como criar chaves e uma pilha de retorno e modificar a pilha de retorno em resposta a 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 no Navigation 3 usando NavEntry
, que é uma classe
que contém uma função combinável. Ele representa um destino, ou seja, uma única parte
de conteúdo que o usuário pode navegar para frente e para trás.
Um NavEntry
também pode conter metadados, que são informações sobre o conteúdo. Esses metadados podem ser lidos por objetos de contêiner, como NavDisplay
, para ajudar a decidir como mostrar 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
, oferecendo armazenamento de dados
versátil.
Para converter um key
em um NavEntry
, crie um provedor de entradas. Essa é uma
função que aceita um key
e retorna um NavEntry
para esse key
. Normalmente, ele é definido como um parâmetro lambda ao criar um NavDisplay
.
Há duas maneiras de criar um provedor de entradas: criando uma função lambda
diretamente ou usando a DSL entryProvider
.
Criar uma função de provedor de entrada diretamente
Normalmente, você cria uma função de provedor de entradas usando uma instrução when
, com uma ramificação para cada uma das suas 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 um deles.
Use a função do builder entryProvider
para isso. Ele também inclui o comportamento de
fallback padrão (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 pilha de retorno
A pilha de retorno representa o estado de navegação do app. Sempre que a pilha de retorno
mudar, a interface do app vai refletir o novo estado da pilha. Na Navegação 3, um
NavDisplay
observa a backstack e atualiza a interface de acordo com ela. Construa
com os seguintes parâmetros:
- Sua pilha de retorno precisa ser do tipo
SnapshotStateList<T>
, em queT
é o tipo das chaves da pilha de retorno. É umList
observável para que ele aciona a recomposição deNavDisplay
quando muda. - Um
entryProvider
para converter as chaves na sua pilha de retorno em objetosNavEntry
. - Se quiser, forneça uma lambda ao parâmetro
onBack
. Isso é chamado quando o usuário aciona um evento de retorno.
O exemplo a seguir mostra como criar um 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, o NavDisplay
mostra o NavEntry
mais alto na pilha de retorno em um layout de painel único. A gravação a seguir mostra o app em execução:

NavDisplay
comportamento padrão 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 pilha de retorno em resposta às interações do usuário.
A mudança no estado da pilha de retorno 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 superior da pilha de retorno em um layout de painel único. Quando a chave principal na pilha de retorno muda, oNavDisplay
usa essa chave para solicitar o conteúdo correspondente do provedor de entradas.O provedor de entradas fornece conteúdo. O provedor de entradas é 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.