Navigationsstatus speichern und verwalten

In den folgenden Abschnitten werden Strategien zum Speichern des Backstacks und zum Speichern des Status beschrieben, der mit Einträgen im Backstack verknüpft ist.

Backstack speichern

Für eine gute Nutzererfahrung ist es wichtig, dass der Navigationsstatus Ihrer App bei verschiedenen Lebenszyklusereignissen erhalten bleibt, einschließlich Konfigurationsänderungen und Prozessende. Bei Navigation 3 sind Sie für den Backstack verantwortlich. Es gibt also keine strengen Richtlinien dazu, wie Sie ihn erstellen oder speichern sollten. Navigation 3 bietet jedoch eine praktische Methode, mit der Sie einen speicherbaren Rückstapel erhalten: rememberNavBackStack.

rememberNavBackStack verwenden

Die zusammensetzbare Funktion rememberNavBackStack dient zum Erstellen eines Backstacks, der bei Konfigurationsänderungen und Prozessende erhalten bleibt.

Damit rememberNavBackStack ordnungsgemäß funktioniert, müssen alle Schlüssel in Ihrem Backstack bestimmte Anforderungen erfüllen:

  • NavKey-Schnittstelle implementieren: Jeder Schlüssel im Backstack muss die NavKey-Schnittstelle implementieren. Dies dient als Markierungsschnittstelle, die der Bibliothek signalisiert, dass der Schlüssel gespeichert werden kann.
  • @Serializable-Anmerkung: Zusätzlich zur Implementierung von NavKey müssen Ihre Schlüsselklassen und ‑objekte mit der Anmerkung @Serializable gekennzeichnet sein.

Das folgende Snippet zeigt eine korrekte Implementierung von rememberNavBackStack:

@Serializable
data object Home : NavKey

@Composable
fun NavBackStack() {
    val backStack = rememberNavBackStack(Home)
}

Alternative: In einer ViewModel speichern

Sie können den Backstack auch in einer ViewModel speichern. Wenn Sie bei Verwendung eines ViewModel- oder eines anderen benutzerdefinierten Speichers Daten auch nach dem Beenden des Prozesses beibehalten möchten, müssen Sie Folgendes tun:

  • Achten Sie darauf, dass Ihre Schlüssel serialisierbar sind: Genau wie bei rememberNavBackStack müssen Ihre Navigationsschlüssel serialisierbar sein.
  • Serialisierung und Deserialisierung manuell verarbeiten: Sie sind dafür verantwortlich, die serialisierte Darstellung jedes Schlüssels manuell im nichtflüchtigen Speicher zu speichern und daraus zu deserialisieren (z.B. SharedPreferences, eine Datenbank oder eine Datei), wenn Ihre App in den Hintergrund wechselt oder wiederhergestellt wird.

ViewModel bis NavEntry Sekunden

ViewModels werden verwendet, um den UI-Status bei Konfigurationsänderungen wie Bildschirmdrehungen beizubehalten. Standardmäßig sind ViewModels auf die nächstgelegene ViewModelStoreOwner beschränkt, in der Regel Ihre Activity oder Fragment.

Möglicherweise möchten Sie jedoch eine ViewModel auf einen bestimmten NavEntry (d.h. einen bestimmten Bildschirm oder ein bestimmtes Ziel) im Backstack anwenden, anstatt auf die gesamte Activity. So wird sichergestellt, dass der Zustand der ViewModel nur so lange beibehalten wird, wie sich diese NavEntry im Backstack befindet, und gelöscht wird, wenn die NavEntry herausgepoppt wird.

Die Add-on-Bibliothek androidx.lifecycle:lifecycle-viewmodel-navigation3 bietet eine NavEntryDecorator, die dies vereinfacht. Dieser Decorator stellt für jede NavEntry eine ViewModelStoreOwner bereit. Wenn Sie ein ViewModel im Inhalt eines NavEntry erstellen (z.B. mit viewModel() in Compose), wird es automatisch auf den Schlüssel dieses NavEntry im Backstack beschränkt. Das bedeutet, dass die ViewModel erstellt wird, wenn die NavEntry dem Backstack hinzugefügt wird, und gelöscht wird, wenn sie entfernt wird.

So verwenden Sie NavEntryDecorator, um ViewModels auf NavEntrys einzugrenzen:

  1. Fügen Sie der Datei app/build.gradle.kts die Abhängigkeit androidx.lifecycle:lifecycle-viewmodel-navigation3 hinzu.
  2. Fügen Sie beim Erstellen eines NavDisplay rememberSavedStateNavEntryDecorator() der Liste der entryDecorators hinzu.
  3. Fügen Sie Ihrem NavDisplay weitere Dekorationen hinzu.

NavDisplay(
    entryDecorators = listOf(
        // Add the default decorators for managing scenes and saving state
        rememberSceneSetupNavEntryDecorator(),
        rememberSavedStateNavEntryDecorator(),
        // Then add the view model store decorator
        rememberViewModelStoreNavEntryDecorator()
    ),
    backStack = backStack,
    entryProvider = entryProvider { },
)