Die NavController enthält einen „Backstack“ mit den Zielen, die der Nutzer besucht hat. Wenn der Nutzer in Ihrer App zu verschiedenen Bildschirmen navigiert, fügt NavController dem Backstack Ziele hinzu und entfernt sie daraus.
Als Stapel ist der Backstack eine „Last in, first out“-Datenstruktur. NavController fügt Elemente also oben auf den Stapel ein und entfernt sie von dort.
Grundlegendes Verhalten
Dies sind die wichtigsten Fakten, die Sie in Bezug auf das Verhalten des Backstacks berücksichtigen sollten:
- Erstes Ziel:Wenn der Nutzer die App öffnet, wird das erste Ziel mit
NavControlleroben auf den Backstack gelegt. - Auf den Stapel legen:Bei jedem Aufruf
NavController.navigate()wird das angegebene Ziel oben auf den Stapel gelegt. - Pop-up-Ziel: Wenn Sie auf Nach oben oder Zurück tippen, werden die Methoden
NavController.navigateUp()bzw.NavController.popBackStack()aufgerufen. Sie entfernen das oberste Ziel aus dem Stapel. Weitere Informationen zum Unterschied zwischen Aufwärts und Zurück finden Sie auf der Seite Navigationsgrundsätze.
Zurück
Die Methode NavController.popBackStack() versucht, das aktuelle Ziel aus dem Backstack zu entfernen und zum vorherigen Ziel zu navigieren. Dadurch wird der Nutzer effektiv einen Schritt in seinem Navigationsverlauf zurückgesetzt. Es wird ein boolescher Wert zurückgegeben, der angibt, ob das Zurückkehren zum Ziel erfolgreich war.
Zurück zu einem bestimmten Zielort wechseln
Sie können auch popBackStack() verwenden, um zu einem bestimmten Ziel zu navigieren. Verwenden Sie dazu eine der Überladungen. Es gibt mehrere, mit denen Sie eine Kennung übergeben können, z. B. eine Ganzzahl id oder einen String route. Diese Überladungen leiten den Nutzer zum Ziel weiter, das mit der angegebenen Kennung verknüpft ist. Wichtig ist, dass sie alles auf dem Stapel über diesem Ziel entfernen.
Diese Überladungen akzeptieren auch einen booleschen inclusive-Wert. Er bestimmt, ob NavController das angegebene Ziel nach der Navigation dorthin auch aus dem Backstack entfernen soll.
Hier ein kurzes Beispiel:
navController.popBackStack(R.id.destinationId, true)
Hier wird NavController mit der Ganzzahl-ID destinationId wieder zum Ziel zurückgeführt. Da der Wert des inclusive-Arguments true ist, wird das angegebene Ziel auch durch NavController aus dem Backstack entfernt.
Fehlgeschlagene Pop-Backs verarbeiten
Wenn popBackStack() den Wert false zurückgibt, gibt ein nachfolgender Aufruf von NavController.getCurrentDestination() den Wert null zurück. Das bedeutet, dass die App das letzte Ziel aus dem Backstack entfernt hat. In diesem Fall sieht der Nutzer nur einen leeren Bildschirm.
Das kann in den folgenden Fällen passieren:
popBackStack()hat nichts aus dem Stapel entfernt.popBackStack()hat ein Ziel aus dem Backstack entfernt und der Stack ist jetzt leer.
Um das Problem zu beheben, müssen Sie zu einem neuen Ziel navigieren oder finish() für Ihre Aktivität aufrufen, um sie zu beenden. Das folgende Snippet veranschaulicht dies:
kotlin
...
if (!navController.popBackStack()) {
// Call finish() on your Activity
finish()
}
Java
...
if (!navController.popBackStack()) {
// Call finish() on your Activity
finish();
}
Pop-up-Fenster für ein Ziel
Wenn Sie Ziele aus dem Backstack entfernen möchten, wenn Sie von einem Ziel zu einem anderen navigieren, fügen Sie dem zugehörigen navigate()-Funktionsaufruf ein popUpTo()-Argument hinzu. popUpTo() weist die Navigationsbibliothek an, einige Ziele aus dem Backstack zu entfernen, wenn navigate() aufgerufen wird. Der Parameterwert ist die Kennzeichnung eines Ziels im Backstack. Die Kennung kann eine Ganzzahl id oder ein String route sein.
Sie können ein Argument für den Parameter inclusive mit dem Wert true einfügen, um anzugeben, dass das in popUpTo() angegebene Ziel auch aus dem Backstack entfernt werden soll.
Um dies programmatisch zu implementieren, übergeben Sie popUpTo() an navigate() als Teil von NavOptions, wobei inclusive auf true festgelegt ist. Das funktioniert sowohl in Compose als auch in Views.
Status beim Einblenden speichern
Wenn Sie popUpTo verwenden, um zu einem Ziel zu navigieren, können Sie optional den Backstack und die Status aller Ziele speichern, die aus dem Backstack entfernt wurden. Sie können den Backstack und die Ziele dann wiederherstellen, wenn Sie später zu diesem Ziel navigieren. So können Sie den Status für ein bestimmtes Ziel beibehalten und mehrere Backstacks haben.
Wenn Sie dies programmatisch tun möchten, geben Sie saveState = true an, wenn Sie popUpTo zu Ihren Navigationsoptionen hinzufügen.
Sie können auch restoreState = true in Ihren Navigationsoptionen angeben, um den Backstack und den mit dem Ziel verknüpften Status automatisch wiederherzustellen.
Beispiel:
navController.navigate(
route = route,
navOptions = navOptions {
popUpTo<A>{ saveState = true }
restoreState = true
}
)
Wenn Sie das Speichern und Wiederherstellen des Status in XML aktivieren möchten, definieren Sie popUpToSaveState als true und restoreState als true in der zugehörigen action.
Beispiel für das Verfassen
Hier ein vollständiges Beispiel in 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")
}
}
Sie haben folgende Möglichkeiten, den Aufruf von NavController.navigate() genauer zu steuern:
// 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
}
Allgemeine Informationen zum Übergeben von Optionen an NavController.navigate() finden Sie im Leitfaden „Mit Optionen navigieren“.
Beispiel für XML
Hier ist ein Beispiel für popUpTo in XML mit einer Aktion:
<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"/>
Pop mit Aktionen
Wenn Sie mit einer Aktion navigieren, können Sie optional zusätzliche Ziele aus dem Backstack entfernen. Wenn Ihre App beispielsweise einen anfänglichen Anmeldevorgang hat, sollten Sie nach der Anmeldung eines Nutzers alle anmeldebezogenen Ziele aus dem Back Stack entfernen, damit Nutzer nicht über den Button „Zurück“ zum Anmeldevorgang zurückkehren.
Weitere Informationen
Weitere Informationen finden Sie auf den folgenden Seiten:
- Kreisförmige Navigation: Hier erfahren Sie, wie Sie einen überfüllten Backstack bei kreisförmigen Navigationsabläufen vermeiden können.
- Dialogziele: Hier erfahren Sie, welche besonderen Aspekte bei der Verwaltung des Backstacks bei Dialogzielen zu berücksichtigen sind.