O NavController contém uma "backstack" que contém os destinos aos quais o usuário
visitou. À medida que o usuário navega para outras telas no app, o
NavController adiciona destinos à backstack e os remove dela.
Dentro da pilha, a backstack é uma estrutura de dados "último a chegar, primeiro a sair". A
Portanto, o NavController empurra e exibe itens da parte de cima da
pilha.
Comportamento básico
Estes são os principais fatos que você precisa considerar sobre o comportamento da backstack:
- Primeiro destino: quando o usuário abre o app, o
NavControllerenvia o primeiro destino para a parte de cima da backstack. - Enviar para a pilha: cada chamada
NavController.navigate()envia o destino especificado para a parte de cima da pilha. - Abrir o destino superior: tocar em Up ou Back chama os métodos
NavController.navigateUp()eNavController.popBackStack(), respectivamente. Eles retiram o destino superior da pilha. Consulte a página Princípios de navegação para mais informações sobre a diferença entre Up e Back.
Retornar
O método NavController.popBackStack() tenta retirar o destino atual
da backstack e navegar para o destino anterior. Isso
faz com que o usuário volte uma etapa no histórico de navegação. O método retorna
um booleano indicando se ele retornou para o destino.
Retornar para um destino específico
Você também pode usar popBackStack() para navegar a um destino específico. Para isso,
use uma das sobrecargas dele. Há várias que permitem transmitir um
identificador, como um id inteiro ou uma string route. Essas sobrecargas levam
o usuário ao destino associado ao identificador fornecido. Elas destacam tudo que está acima desse destino na pilha.
Essas sobrecargas também usam um booleano inclusive. Ele determina se o
NavController também precisa retirar o destino especificado da backstack
depois de ter navegado até ele.
Confira este breve exemplo:
navController.popBackStack(R.id.destinationId, true)
Aqui o NavController retorna ao destino com o ID de número inteiro
destinationId. Como o valor do argumento inclusive é true, o
NavController também exibe o destino especificado da backstack.
Processar um retorno com falha
Quando popBackStack() retornar false, uma chamada subsequente para NavController.getCurrentDestination() retornará null. Isso significa que o app
retirou o último destino da backstack. Nesse caso, o usuário vê apenas
uma tela em branco.
Isso pode ocorrer nos seguintes casos:
popBackStack()não exibiu nada da pilha.popBackStack()retirou um destino da backstack, e a pilha agora está vazia.
Para resolver isso, navegue até um novo destino ou chame finish()
na atividade para encerrar. O snippet a seguir demonstra isso:
kotlin
...
if (!navController.popBackStack()) {
// Call finish() on your Activity
finish()
}
java
...
if (!navController.popBackStack()) {
// Call finish() on your Activity
finish();
}
Abrir um destino
Para remover destinos da backstack ao navegar de um destino
para outro, adicione um argumento popUpTo() à chamada de função
navigate() associada. popUpTo() instrui a biblioteca de navegação a remover alguns destinos
da backstack como parte da chamada para navigate(). O valor do parâmetro é
o identificador de um destino na backstack. O identificador pode ser um
id inteiro ou uma string route.
Você pode incluir um argumento para o parâmetro inclusive com um valor de true
para indicar que o destino especificado em popUpTo() também deve
ser retirado da backstack.
Para implementar isso de forma programática, transmita popUpTo() para navigate() como parte de
NavOptions com inclusive definido como true. Isso funciona no Compose e
no Views.
Salvar o estado ao abrir
Ao usar popUpTo para navegar até um destino, você tem a opção de salvar o
a backstack e os estados de todos os destinos retirados dela. Você pode
Em seguida, restaura a backstack e os destinos ao navegar até esse destino.
mais tarde. Isso permite preservar o estado de um determinado destino e ter
várias backstacks.
Para fazer isso de forma programática, especifique saveState = true ao adicionar popUpTo a
suas opções de navegação.
Também é possível especificar restoreState = true nas opções de navegação para:
restaurar automaticamente a backstack e o estado associado à
destino.
Exemplo:
navController.navigate(
route = route,
navOptions = navOptions {
popUpTo<A>{ saveState = true }
restoreState = true
}
)
Para ativar o salvamento e a restauração do estado no XML, defina popUpToSaveState como true
e restoreState como true, respectivamente, no action associado.
Exemplo em XML
Confira um exemplo de popUpTo em XML com uma ação:
<action
android:id="@+id/action_a_to_b"
app:destination="@id/b"
app:popUpTo="@+id/a"
app:popUpToInclusive="true"
app:restoreState=”true”
app:popUpToSaveState="true"/>
Exemplo do Compose
Confira a seguir um exemplo completo do mesmo recurso no Compose:
@Composable
fun MyAppNavHost(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
startDestination: Any = A
) {
NavHost(
modifier = modifier,
navController = navController,
startDestination = startDestination
) {
composable<A> {
DestinationA(
onNavigateToB = {
// Pop everything up to, and including, the A destination off
// the back stack, saving the back stack and the state of its
// destinations.
// Then restore any previous back stack state associated with
// the B destination.
// Finally navigate to the B destination.
navController.navigate(route = B) {
popUpTo<A> {
inclusive = true
saveState = true
}
restoreState = true
}
},
)
}
composable<B> { DestinationB(/* ... */) }
}
}
@Composable
fun DestinationA(onNavigateToB: () -> Unit) {
Button(onClick = onNavigateToB) {
Text("Go to A")
}
}
Mais detalhadamente, você pode mudar a forma como chama NavController.navigate() das
seguintes maneiras:
// Pop everything up to the destination_a destination off the back stack before
// navigating to the "destination_b" destination
navController.navigate("destination_b") {
popUpTo("destination_a")
}
// Pop everything up to and including the "destination_a" destination off
// the back stack before navigating to the "destination_b" destination
navController.navigate("destination_b") {
popUpTo("destination_a") { inclusive = true }
}
// Navigate to the "search” destination only if we’re not already on
// the "search" destination, avoiding multiple copies on the top of the
// back stack
navController.navigate("search") {
launchSingleTop = true
}
Para informações gerais sobre como transmitir opções para NavController.navigate(), consulte
o Guia de navegação com opções.
Destacar usando ações
Ao navegar usando uma ação, você também pode retirar destinos adicionais da backstack. Por exemplo, se o app tiver um fluxo de login inicial, assim que um usuário tiver feito login, todos os destinos relacionados ao login precisarão ser retirados da backstack para que o botão" "Voltar" não retorne os usuários ao fluxo de login.
Leitura adicional
Para mais informações, confira as seguintes páginas:
- Navegação circular: aprenda a evitar uma backstack sobrecarregada nos casos em que os fluxos de navegação são circulares.
- Destinos da caixa de diálogo: leia sobre como os destinos da caixa de diálogo introduzem considerações exclusivas sobre como gerenciar a backstack.