Logik oder Wrapper auf Ziele anwenden

Mit der Klasse NavEntryDecorator können Sie zusätzliche Informationen angeben oder dieselbe Logik auf Ziele anwenden. Diese Klasse umschließt jeden NavEntry in einem Back Stack mit einer zusammensetzbaren Funktion. Anders ausgedrückt: Der Inhalt des Eintrags wird dekoriert.

Benutzerdefinierten Decorator erstellen

Wenn Sie einen Decorator erstellen möchten, erweitern Sie die Klasse NavEntryDecorator und überschreiben Sie die folgenden Methoden:

  • decorate: Ein zusammensetzbares Lambda, das für jeden NavEntry im Back Stack aufgerufen wird. Sie empfängt die NavEntry als Parameter. So können Sie Zustandsobjekte erstellen, die dem contentKey des Eintrags zugeordnet sind. Mit CompositionLocalProvider können Sie Abhängigkeiten für den Inhalt des Eintrags bereitstellen. Sie können den Inhalt auch mit einer zusammensetzbaren Funktion umschließen oder Nebenwirkungen auslösen. Sie sollten entry.Content() immer innerhalb dieser Methode aufrufen.
  • onPop: Ein Callback, der aufgerufen wird, wenn ein NavEntry aus dem Back Stack entfernt wurde und die Komposition verlassen hat. Sie empfängt den contentKey des entfernten Eintrags. Verwenden Sie die contentKey, um alle mit diesem Eintrag verknüpften Status zu identifizieren und zu bereinigen.

Im folgenden Beispiel wird die Klasse NavEntryDecorator erweitert, um einen benutzerdefinierten Decorator zu erstellen.

// import androidx.navigation3.runtime.NavEntryDecorator
class CustomNavEntryDecorator<T : Any> : NavEntryDecorator<T>(
    decorate = { entry ->
        Log.d("CustomNavEntryDecorator", "entry with ${entry.contentKey} entered composition and was decorated")
        entry.Content()
    },
    onPop = { contentKey -> Log.d("CustomNavEntryDecorator", "entry with $contentKey was popped") }
)

Wenn Ihr Decorator Zugriff auf den Status benötigt, erstellen Sie eine zusammensetzbare Funktion, die diesen Status erstellt, und verwenden Sie sie dann, um den Decorator zu erstellen. Ein Beispiel für eine Implementierung finden Sie im Quellcode für rememberSaveableStateHolderNavEntryDecorator. Dadurch wird der Status (ein SaveableStateHolder) erstellt und zum Erstellen des Decorators verwendet.

Back Stack dekorieren

Nachdem Sie den NavEntryDecorator erstellt haben, können Sie die Einträge im Back Stack auf zwei Arten dekorieren:

  • Verwenden Sie rememberDecoratedNavEntries. Diese Funktion ist nützlich, wenn Sie mehrere Back Stacks haben, die jeweils eigene Decorators haben. Weitere Informationen finden Sie in diesem Code-Rezept. Die Funktion gibt eine dekorierte Liste von NavEntrys zurück, die Sie mit NavDisplay verwenden können.
  • Geben Sie Ihren Decorator mit dem Parameter entryDecorators direkt an NavDisplay weiter. NavDisplay ruft im Hintergrund rememberDecoratedNavEntries auf und zeigt die dekorierten Einträge an.

Standard-Decorator einbeziehen

Navigation 3 enthält einen Standard-Decorator namens SaveableStateHolderNavEntryDecorator, mit dem der Status eines NavEntry bei Konfigurationsänderungen und Prozessbeendigungen beibehalten werden kann. Sie umschließt NavEntry-Inhalte mit einem SaveableStateProvider, sodass rememberSaveable-Aufrufe innerhalb des NavEntry-Inhalts korrekt funktionieren.

Sofern Ihr Decorator keinen SaveableStateProvider bereitstellt, sollten Sie SaveableStateHolderNavEntryDecorator als ersten Decorator in die Liste der bereitgestellten Decorators aufnehmen. Sie wird mit rememberSaveableStateHolderNavEntryDecorator erstellt.

Beispiel:

// import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
NavDisplay(
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        remember { CustomNavEntryDecorator() }
    ),
    // ...
)

Ergebnisse mit ResultEventBusNavEntryDecorator übergeben

Ab Navigation 3 1.2.0 können Sie ResultEventBusNavEntryDecorator verwenden, um jedem NavEntry einen ResultEventBus mit der CompositionLocal LocalResultEventBus bereitzustellen.

Standardmäßig erstellt rememberResultEventBusNavEntryDecorator eine eigene ResultEventBus-Instanz und speichert sie intern mit rememberResultEventBus. Wenn Sie außerhalb der Decorator-Hierarchie auf den Event Bus zugreifen müssen (z. B. auf der obersten Ebene des App-Gerüsts), können Sie den ResultEventBus hochstufen, indem Sie rememberResultEventBus aufrufen und an rememberResultEventBusNavEntryDecorator(resultEventBus) übergeben:

val resultEventBus = rememberResultEventBus()

NavDisplay(
    /* ... */
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        rememberResultEventBusNavEntryDecorator(resultEventBus = resultEventBus)
    )
)

Weitere Informationen zum Senden und Beobachten von Ergebnissen finden Sie unter Ergebnisse zurückgeben.

Wann sollte ein Decorator verwendet werden?

Mit einem Decorator können Sie Folgendes tun:

  • Erstellen Sie für jedes NavEntry in einem Back Stack eine Abhängigkeit. Beispiel: ViewModelStoreNavEntryDecorator erstellt für jede NavEntry eine ViewModelStore.
  • Ergebnisse weitergeben und zwischen Zielen kommunizieren. Beispielsweise bietet die ResultEventBusNavEntryDecorator einen ResultEventBus zu Zielen im Back Stack.
  • Ein Objekt auf mehrere NavEntrys beschränken. Beispiel: Um einen ViewModel zwischen mehreren Einträgen zu teilen.
  • Führen Sie dieselbe Aktion für mehrere NavEntrys aus. Beispielsweise, um Logging-, Debugging- oder Tracing-Vorgänge für jeden Eintrag auszuführen.
  • NavEntrys mit derselben zusammensetzbaren Funktion umschließen.
  • Bereinigen Sie den mit NavEntrys verknüpften Status. Wenn beispielsweise ein Eintrag aus dem Back Stack entfernt wird, löscht der ViewModelStoreNavEntryDecorator die zugehörige ViewModelStore.

Verwenden Sie keinen Decorator für Folgendes:

  • Übergeben Sie eine Abhängigkeit an eine einzelne NavEntry.
  • Abhängigkeiten bereitstellen, deren Bereich größer als der Back Stack ist.

In beiden Fällen übergeben Sie die Abhängigkeit stattdessen direkt beim Erstellen des NavEntry.

Weitere Codebeispiele finden Sie unter NavEntryDecorator.