Navigation und Back Stack

Das NavController enthält einen „Back-Stack“ mit den Zielen, die der Nutzer besucht hat. Wenn der Nutzer zu Bildschirmen in Ihrer App navigiert, werden vom NavController Ziele zum Back-Stack hinzugefügt und daraus entfernt.

Als Stack wird der Back-Stack als „Last In, First Out“-Datenstruktur bezeichnet. Der NavController verschiebt Elemente daher zum oberen Rand des Stapels und entfernt sie vom Anfang des Stapels.

Grundlegende Funktionsweise

Dies sind die wichtigsten Fakten zum Verhalten des Backstacks:

  • Erstes Ziel:Wenn der Nutzer die App öffnet, verschiebt NavController das erste Ziel nach oben im Back-Stack.
  • Per Push in den Stack übertragen: Bei jedem NavController.navigate()-Aufruf wird das angegebene Ziel an den Anfang des Stacks verschoben.
  • Top-Ziel einblenden: Wenn Sie auf Nach oben oder Zurück tippen, werden die Methoden NavController.navigateUp() bzw. NavController.popBackStack() aufgerufen. Das oberste Ziel wird vom Stapel gelöst. Weitere Informationen zum Unterschied zwischen den beiden Seiten Nach oben und Zurück finden Sie auf der Seite Grundlagen der Navigation.

Zurück

Mit der Methode NavController.popBackStack() wird versucht, das aktuelle Ziel aus dem Back-Stack zu entfernen und zum vorherigen Ziel zu wechseln. Dadurch wird der Nutzer im Navigationsverlauf einen Schritt zurückversetzt. Sie gibt einen booleschen Wert zurück, der angibt, ob die Verbindung erfolgreich an das Ziel übergeben wurde.

Zu einem bestimmten Ziel zurückkehren

Sie können auch popBackStack() verwenden, um zu einem bestimmten Ziel zu navigieren. Verwenden Sie dazu eine der Überlastungen. Es gibt mehrere Möglichkeiten, eine ID zu übergeben, z. B. eine Ganzzahl id oder einen String route. Diese Überlastungen bringen den Nutzer zu dem Ziel, das der angegebenen Kennung zugeordnet ist. Entscheidend ist, dass sie alle Elemente auf dem Stack über dem Ziel platzieren.

Für diese Überlasten wird auch ein boolescher Wert vom Typ inclusive verwendet. Damit wird festgelegt, ob das angegebene Ziel auch aus dem Back-Stack entfernt werden soll, nachdem das NavController aufgerufen wurde.

Sehen Sie sich zum Beispiel dieses kurze Snippet an:

navController.popBackStack(R.id.destinationId, true)

Hier wird NavController wieder zum Ziel mit der Ganzzahl-ID destinationId zurückgegeben. Da der Wert des Arguments inclusive true ist, entfernt der NavController auch das angegebene Ziel aus dem Back-Stack.

Umgang mit einem fehlgeschlagenen Pop-back

Wenn popBackStack() den Wert false zurückgibt, wird bei einem nachfolgenden Aufruf von NavController.getCurrentDestination() null zurückgegeben. Das bedeutet, dass die App das letzte Ziel aus dem Back Stack entfernt hat. In diesem Fall sieht der Nutzer nur einen leeren Bildschirm.

Das kann in den folgenden Fällen vorkommen:

  • popBackStack() hat nichts aus dem Stapel gezogen.
  • popBackStack() hat ein Ziel aus dem Back Stack entfernt und der Stack ist jetzt leer.

Um dieses Problem zu beheben, müssen Sie ein neues Ziel aufrufen 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();
}

Zu einem Ziel wechseln

Wenn Sie bei der Navigation von einem Ziel zu einem anderen Ziele aus dem Back-Stack entfernen möchten, fügen Sie dem zugehörigen navigate()-Funktionsaufruf ein popUpTo()-Argument hinzu. popUpTo() weist die Navigationsbibliothek an, im Rahmen des navigate()-Aufrufs einige Ziele aus dem Back Stack zu entfernen. Der Parameterwert ist die Kennung eines Ziels auf dem Back-Stack. Die Kennzeichnung kann eine Ganzzahl id oder ein String des Typs route sein.

Sie können ein Argument für den Parameter inclusive mit dem Wert true angeben, um anzugeben, dass das in popUpTo() angegebene Ziel auch aus dem Back-Stack herauskommen soll.

Wenn Sie dies programmatisch implementieren möchten, übergeben Sie popUpTo() als Teil von NavOptions an navigate(), wobei inclusive auf true gesetzt ist. Dies funktioniert sowohl in der Schreibfunktion als auch in der Ansicht.

Status beim Pop-up speichern

Wenn Sie mit popUpTo zu einem Ziel navigieren, können Sie optional die Status aller Ziele speichern, die aus dem Back-Stack herausgenommen werden.

Definieren Sie zum Aktivieren dieser Option popUpToSaveState als true in der zugehörigen action oder rufen Sie NavController.navigate() auf.

Wenn Sie zu einem Ziel gehen, können Sie restoreSaveState auch als true definieren, um automatisch den Status wiederherzustellen, der dem Ziel in der destination-Property zugeordnet ist.

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"/>

Beispiele für die Erstellung

Im Folgenden finden Sie ein vollständiges Beispiel dafür in der Funktion „Compose“:

@Composable
fun MyAppNavHost(
    modifier: Modifier = Modifier,
    navController: NavHostController = rememberNavController(),
    startDestination: String = "destination_a"
) {
    NavHost(
        modifier = modifier,
        navController = navController,
        startDestination = startDestination
    ) {
        composable("destination_a") {
            DestinationA(
                onNavigateToB = {
                // 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") {
                            inclusive = true
                            saveState = true
                        }
                    }
                },
            )
        }
        composable("destination_b") { DestinationB(/* ... */) }
    }
}

@ Composable
fun DestinationA(onNavigateToB: () -> Unit) {
    Button(onClick = onNavigateToB) {
        Text("Go to A")
    }
}

Sie können die Aufruffunktion von NavController.navigate() auch folgendermaßen ändern:

// 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 zur Navigation mit Optionen.

Pop mit Aktionen

Wenn Sie mithilfe einer Aktion navigieren, können Sie optional zusätzliche Ziele aus dem Back-Stack entfernen. Wenn Ihre Anwendung beispielsweise einen anfänglichen Anmeldevorgang hat, sollten Sie nach der Anmeldung eines Nutzers alle anmeldungsbezogenen Ziele aus dem Back-Stack entfernen, damit die Schaltfläche „Zurück“ die Nutzer nicht zurück zum Anmeldevorgang führt.

Zusätzliche Lesematerialien

Weitere Informationen finden Sie auf den folgenden Seiten:

  • Kreisförmige Navigation: Hier erfahren Sie, wie Sie einen überfüllten Backstack in Fällen mit kreisförmigen Navigationsflüssen vermeiden können.
  • Dialogziele: Lesen Sie, wie Dialogziele besondere Überlegungen bei der Verwaltung Ihres Back Stacks beinhalten.