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
NavController
envia 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.