Navigazione e stack posteriore

NavController contiene uno "stack back" che contiene le destinazioni dell'utente visitato. Quando l'utente passa alle schermate dell'app, NavController aggiunge e rimuove le destinazioni da e verso lo stack precedente.

Essendo una pila, quella posteriore è l'"ultimo, il primo fuori" struttura dei dati. La Di conseguenza, NavController sposta gli elementi nella parte superiore di uno di questi elementi e li apre stack.

Comportamento di base

Questi sono i dati principali da considerare per quanto riguarda il comportamento della schiena stack:

  • Prima destinazione:quando l'utente apre l'app, la NavController che spinge la prima destinazione in cima al back stack.
  • Push allo stack: viene eseguito il push di ogni chiamata NavController.navigate() la destinazione specificata in cima allo stack.
  • Destinazione superiore visualizzata:toccando Su o Indietro viene chiamata la NavController.navigateUp() e NavController.popBackStack() rispettivamente. La destinazione principale viene svincolata dall'elenco. Consulta le Principi di navigazione per ulteriori informazioni sulla differenza tra Alto e Indietro.

Ripiega

Il metodo NavController.popBackStack() tenta di aprire l'elemento corrente dalla destinazione precedente e tornare a quella precedente. Questo riporta l'utente di un passaggio alla cronologia di navigazione. Ritorna un valore booleano che indica se è riuscito a tornare alla destinazione.

Recuperare una destinazione specifica

Puoi anche utilizzare popBackStack() per raggiungere una destinazione specifica. Da fare quindi usa uno dei suoi sovraccarichi. Esistono diversi metodi che ti consentono di passare , ad esempio un numero intero id o una stringa route. Questi sovraccarichi richiedono l'utente alla destinazione associata all'identificatore specificato. In particolare, tutti gli elementi presenti nella pila sopra la destinazione.

Questi sovraccarichi prendono anche un valore booleano inclusive. Stabilisce se le NavController deve anche estrarre la destinazione specificata dallo stack posteriore dopo averlo raggiunto.

Considera ad esempio questo breve snippet:

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

In questo caso, NavController ritorna alla destinazione con ID numero intero destinationId. Poiché il valore dell'argomento inclusive è true, il valore NavController inoltre separa la destinazione specificata dallo stack posteriore.

Gestire un popback non riuscito

Quando popBackStack() restituisce false, una chiamata successiva a NavController.getCurrentDestination() restituisce null. Ciò significa che l'app ha l'ultima destinazione è stata rimossa dal back stack. In questo caso, l'utente vede solo una schermata vuota.

Ciò può verificarsi nei seguenti casi:

  • popBackStack() non ha raccolto nulla dall'elenco filtri.
  • popBackStack() ha spostato una destinazione dallo stack precedente e lo stack è vuoto.

Per risolvere questo problema, devi poi andare a una nuova destinazione o chiamare finish() sulla tua attività per terminarla. Lo snippet seguente dimostra che:

Kotlin

...

if (!navController.popBackStack()) {
    // Call finish() on your Activity
    finish()
}

java

...

if (!navController.popBackStack()) {
    // Call finish() on your Activity
    finish();
}

Spostarsi a una destinazione

Per rimuovere le destinazioni dallo stack posteriore quando si parte da una destinazione a un'altra, aggiungi un argomento popUpTo() alla funzione navigate() associata chiamata. popUpTo() indica alla libreria di navigazione di rimuovere alcune destinazioni dallo stack posteriore nell'ambito della chiamata a navigate(). Il valore del parametro è l'identificatore di una destinazione sul back stack. L'identificatore può essere un numero intero id o stringa route.

Puoi includere un argomento per il parametro inclusive con il valore true per indicare che anche la destinazione specificata in popUpTo() deve sgancia il gruppo posteriore.

Per implementare questa funzionalità in modo programmatico, passa popUpTo() a navigate() come parte di NavOptions con inclusive impostato su true. Funziona sia in Compose Visualizzazioni.

Salva lo stato quando viene visualizzato il popup

Quando utilizzi popUpTo per raggiungere una destinazione, se vuoi, puoi salvare il e gli stati di tutte le destinazioni sono saltati fuori dallo stack. Puoi quindi ripristina lo stack posteriore e le destinazioni quando accedi a quella destinazione in un secondo momento. In questo modo puoi conservare lo stato di una determinata destinazione più back stack.

Per farlo in modo programmatico, specifica saveState = true quando aggiungi popUpTo a le opzioni di navigazione.

Puoi anche specificare restoreState = true nelle opzioni di navigazione per ripristinare automaticamente il back stack e lo stato associato destinazione.

Ad esempio:

navController.navigate(
    route = route,
    navOptions =  navOptions {
        popUpTo<A>{ saveState = true }
        restoreState = true
    }
)

Per attivare il salvataggio e il ripristino dello stato in XML, definisci popUpToSaveState come true e restoreState rispettivamente come true nel gruppo action associato.

Esempio XML

Ecco un esempio di popUpTo in XML, con un'azione:

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

Crea esempio

Di seguito è riportato un esempio completo della procedura 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")
    }
}

In modo più dettagliato, puoi modificare il modo in cui chiami NavController.navigate() nel nei seguenti modi:

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

Per informazioni generali sulle opzioni di trasmissione a NavController.navigate(), consulta consulta la guida "Naviga con le opzioni".

Pop usando le azioni

Durante la navigazione utilizzando un'azione, puoi facoltativamente inserire altre destinazioni dal gruppo posteriore. Ad esempio, se la tua app prevede un flusso di accesso iniziale, una volta un utente ha eseguito l'accesso, devi separare tutte le destinazioni relative all'accesso. dello stack posteriore, in modo che il pulsante Indietro non reindirizzi gli utenti alla pagina di accesso flusso di lavoro.

Letture aggiuntive

Per saperne di più, consulta le seguenti pagine:

  • Navigazione circolare. Scopri come evitare i casi di schiena in eccesso. nei casi in cui i flussi di navigazione sono circolari.
  • Destinazioni delle finestre di dialogo: scopri come introducono le destinazioni delle finestre di dialogo considerazioni specifiche sulla gestione del tuo back stack.