Navigazione e stack posteriore

NavController contiene uno "stack back" contenente le destinazioni visitate dall'utente. Mentre l'utente accede alle schermate dell'app, NavController aggiunge e rimuove le destinazioni da e verso lo stack di backup.

In quanto stack, lo stack di back è una struttura di dati "l'ultimo accesso, il primo all'uscita". Di conseguenza, l'elemento NavController esegue il push di elementi all'interno dello stack e lo mostra a sua volta dalla parte superiore.

Comportamento di base

Di seguito sono riportati gli aspetti principali da considerare in merito al comportamento dello stack posteriore:

  • Prima destinazione: quando l'utente apre l'app, NavController invia la prima destinazione alla parte superiore dello stack posteriore.
  • Push allo stack: ogni chiamata NavController.navigate() esegue il push della destinazione specificata in cima allo stack.
  • Per attivare la destinazione principale: se tocchi Su o Indietro vengono richiamati rispettivamente i metodi NavController.navigateUp() e NavController.popBackStack(). Escono dalla pila la destinazione principale. Consulta la pagina Principi di navigazione per ulteriori informazioni sulla differenza tra Freccia su e Indietro.

Torna indietro

Il metodo NavController.popBackStack() tenta di estrarre la destinazione attuale dallo stack posteriore e di passare a quella precedente. In questo modo, l'utente può tornare indietro di un passaggio nella cronologia di navigazione. Restituisce un valore booleano che indica se è tornato alla destinazione.

Torna a una destinazione specifica

Puoi anche utilizzare popBackStack() per raggiungere una determinata destinazione. Per farlo, utilizza uno dei suoi sovraccarichi. Ce ne sono diversi che ti consentono di passare un identificatore, come un numero intero id o una stringa route. Questi sovraccarichi portano l'utente alla destinazione associata all'identificatore specificato. Fondamentalmente, mettono tutto nello stack sopra la destinazione.

Questi sovraccarichi utilizzano anche un valore booleano inclusive. Stabilisce se NavController deve anche estrarre la destinazione specificata dallo stack di riserva dopo aver eseguito l'accesso.

Come esempio, considera questo breve snippet:

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

Qui il campo NavController torna alla destinazione con l'ID numero intero destinationId. Poiché il valore dell'argomento inclusive è true, NavController fa emergere anche la destinazione specificata dallo stack back.

Gestire un popback non riuscito

Quando popBackStack() restituisce false, una chiamata successiva a NavController.getCurrentDestination() restituisce null. Questo significa che l'app ha scaricato l'ultima destinazione dallo stack di riserva. In questo caso, l'utente vede solo una schermata vuota.

Ciò può verificarsi nei seguenti casi:

  • popBackStack() non ha saltato nulla dall'elenco filtri.
  • popBackStack() ha rimosso una destinazione dallo stack posteriore e lo stack è ora vuoto.

Per risolvere il problema, devi accedere a una nuova destinazione o chiamare finish() sulla tua attività per terminarla. Lo snippet riportato di seguito lo dimostra:

Kotlin

...

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

java

...

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

Vai a una destinazione

Per rimuovere le destinazioni dallo stack posteriore durante il passaggio da una destinazione a un'altra, aggiungi un argomento popUpTo() alla chiamata di funzione navigate() associata. popUpTo() indica alla libreria di navigazione di rimuovere alcune destinazioni dallo stack posteriore durante la chiamata a navigate(). Il valore del parametro è l'identificatore di una destinazione sullo stack posteriore. L'identificatore può essere un numero intero id o una stringa route.

Puoi includere un argomento per il parametro inclusive con un valore di true per indicare che anche la destinazione specificata in popUpTo() deve uscire dallo stack di ritorno.

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

Salva lo stato al popup

Quando utilizzi popUpTo per navigare verso una destinazione, puoi scegliere di salvare gli stati di tutte le destinazioni estratti dallo stack di supporto.

Per attivare questa opzione, definisci popUpToSaveState come true nell'elemento action associato o chiama il numero NavController.navigate().

Quando raggiungi una destinazione, puoi anche definire restoreSaveState come true per ripristinare automaticamente lo stato associato alla destinazione nella proprietà destination.

Esempio XML

Ecco un esempio di popUpTo in XML, utilizzando 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"/>

Esempi di scrittura

Di seguito è riportato un esempio completo dello stesso in Scrivi:

@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")
    }
}

In modo più dettagliato, puoi modificare il modo in cui chiami NavController.navigate() 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 su come passare opzioni a NavController.navigate(), consulta la guida Navigare con le opzioni.

Pop con azioni

Durante la navigazione utilizzando un'azione, puoi facoltativamente rimuovere altre destinazioni dallo stack di riserva. Ad esempio, se la tua app prevede un flusso di accesso iniziale, dopo che un utente ha eseguito l'accesso dovresti estrarre tutte le destinazioni correlate all'accesso dallo stack di backup in modo che il pulsante Indietro non reindirizzi gli utenti al flusso di accesso.

Letture aggiuntive

Per ulteriori informazioni, consulta le seguenti pagine: