Navigationsstatus speichern und verwalten

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

Backstack speichern

Es ist wichtig, dass der Navigationsstatus Ihrer App bei verschiedenen Lebenszyklusereignissen beibehalten wird, einschließlich Konfigurationsänderungen und Prozessbeendigung, um eine gute Nutzererfahrung zu gewährleisten. In Navigation 3 gehört der Backstack Ihnen. 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 Backstack erstellen können: rememberNavBackStack.

rememberNavBackStack verwenden

Die zusammensetzbare Funktion rememberNavBackStack wurde entwickelt, um einen Backstack zu erstellen, der Konfigurationsänderungen und das Beenden von Prozessen überdauert.

Damit rememberNavBackStack richtig funktioniert, muss jeder 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-Annotation: Zusätzlich zur Implementierung von NavKey müssen Ihre Schlüsselklassen und -objekte mit der @Serializable-Annotation gekennzeichnet werden.

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

Eine weitere Möglichkeit, den Backstack zu verwalten, besteht darin, ihn in einem ViewModel zu speichern. Wenn Sie bei Verwendung von ViewModel oder einem anderen benutzerdefinierten Speicher die Persistenz über das Beenden von Prozessen hinweg beibehalten möchten, müssen Sie Folgendes tun:

  • Schlüssel müssen serialisierbar sein: 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 in einem persistenten Speicher (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-bezogenen Status bei Konfigurationsänderungen wie Bildschirmdrehungen beizubehalten. Standardmäßig sind ViewModels auf die nächstgelegene ViewModelStoreOwner beschränkt, in der Regel auf Ihre Activity oder Fragment.

Möglicherweise möchten Sie den Bereich eines ViewModel auf einen bestimmten NavEntry (d.h. einen bestimmten Bildschirm oder eine bestimmte Zielanwendung) im Backstack und nicht auf das gesamte Activity beschränken. So wird sichergestellt, dass der Status von ViewModel nur beibehalten wird, solange NavEntry Teil des Backstacks ist. Er wird gelöscht, wenn NavEntry aus dem Stack entfernt wird.

Die Add-on-Bibliothek androidx.lifecycle:lifecycle-viewmodel-navigation3 bietet eine NavEntryDecorator, die dies erleichtert. Dieser Dekorator stellt für jede NavEntry ein 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 ViewModel erstellt wird, wenn NavEntry dem Backstack hinzugefügt wird, und gelöscht wird, wenn es entfernt wird.

So verwenden Sie NavEntryDecorator, um ViewModels auf NavEntrys zu beschränken:

  1. Fügen Sie der Datei app/build.gradle.kts die Abhängigkeit androidx.lifecycle:lifecycle-viewmodel-navigation3 hinzu.
  2. Fügen Sie rememberSaveableStateHolderNavEntryDecorator() der Liste der entryDecorators hinzu, wenn Sie ein NavDisplay erstellen.
  3. Fügen Sie Ihrem NavDisplay weitere Dekoratoren hinzu.

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