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 jedes NavEntry in einem Backstack mit einer zusammensetzbaren Funktion. Anders gesagt: Sie gestaltet den Inhalt des Eintrags.

Benutzerdefinierten Dekorator erstellen

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

  • decorate: Eine zusammensetzbare Lambda-Funktion, die für jedes NavEntry in Ihrem Backstack aufgerufen wird. Es empfängt NavEntry als Parameter. So können Sie Statusobjekte erstellen, die auf den contentKey des Eintrags basieren. Mit CompositionLocalProvider können Sie Abhängigkeiten für den Inhalt des Eintrags angeben. Sie können den Inhalt auch in eine zusammensetzbare Funktion einfügen oder Nebeneffekte auslösen. Sie sollten entry.Content() immer in dieser Methode aufrufen.
  • onPop: Ein Callback, der aufgerufen wird, wenn ein NavEntry aus dem Backstack entfernt wurde und die Komposition verlassen hat. Sie erhält die contentKey des entfernten Eintrags. Verwenden Sie die contentKey, um den mit diesem Eintrag verknüpften Status zu identifizieren und zu bereinigen.

Im folgenden Beispiel wird die Klasse NavEntryDecorator erweitert, um einen benutzerdefinierten Dekorator 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 Dekorator Zugriff auf den Status benötigt, erstellen Sie eine komponierbare Funktion, die diesen Status erstellt, und verwenden Sie ihn dann, um den Dekorator zu erstellen. Ein Beispiel für die Implementierung finden Sie im Quellcode für rememberSaveableStateHolderNavEntryDecorator. Dadurch wird der Status – ein SaveableStateHolder – erstellt und zum Erstellen des Decorators verwendet.

Backstack dekorieren

Nachdem Sie NavEntryDecorator erstellt haben, können Sie die Einträge in Ihrem Backstack auf zwei Arten dekorieren:

  • Verwenden Sie rememberDecoratedNavEntries. Diese Funktion ist nützlich, wenn Sie mehrere Backstacks mit jeweils eigenen Dekoratoren haben (siehe dieses Codebeispiel). Die Funktion gibt eine dekorierte Liste von NavEntry zurück, die Sie mit NavDisplay verwenden können.
  • Stellen Sie Ihren Decorator direkt für NavDisplay bereit, indem Sie den Parameter entryDecorators verwenden. NavDisplay ruft rememberDecoratedNavEntries im Hintergrund auf und zeigt die dekorierten Einträge an.

Standard-Decorator einfügen

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

Sofern Ihr Dekorator keine SaveableStateProvider bereitstellt, sollten Sie SaveableStateHolderNavEntryDecorator als ersten Dekorator in die Liste der bereitgestellten Dekoratoren 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 mit ResultEventBusNavEntryDecorator jedem NavEntry über die lokale Komposition LocalResultEventBus eine ResultEventBus bereitstellen.

Standardmäßig erstellt und speichert rememberResultEventBusNavEntryDecorator intern eine eigene ResultEventBus-Instanz mit rememberResultEventBus. Wenn Sie außerhalb der Dekoratorhierarchie (z. B. im App-Scaffolding auf oberster Ebene) auf den Ereignisbus zugreifen müssen, können Sie ResultEventBus durch Aufrufen von rememberResultEventBus und Übergeben an rememberResultEventBusNavEntryDecorator(resultEventBus) hochziehen:

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 Dekorator verwendet werden?

Mit einem Decorator können Sie:

  • Erstellen Sie für jedes NavEntry in einem Backstack eine Abhängigkeit. Mit ViewModelStoreNavEntryDecorator wird beispielsweise für jede NavEntry ein ViewModelStore erstellt.
  • Ergebnisse übergeben und zwischen Zielen kommunizieren. Beispielsweise bietet ResultEventBusNavEntryDecorator einen ResultEventBus für Ziele im Backstack.
  • Ein Objekt mehreren NavEntrys zuweisen. So können Sie beispielsweise ein ViewModel für mehrere Einträge freigeben.
  • Führen Sie dieselbe Aktion für mehrere NavEntry aus. Sie können beispielsweise für jeden Eintrag Protokollierungs-, Debugging- oder Tracing-Vorgänge ausführen.
  • Umschließe NavEntrys mit derselben zusammensetzbaren Funktion.
  • Bereinigen Sie den mit NavEntrys verknüpften Status. Wenn beispielsweise ein Eintrag aus dem Backstack entfernt wird, löscht ViewModelStoreNavEntryDecorator die zugehörige ViewModelStore.

Verwenden Sie keinen Decorator für Folgendes:

  • Eine Abhängigkeit an ein einzelnes NavEntry übergeben.
  • Stellen Sie Abhängigkeiten bereit, deren Bereich breiter als der Backstack ist.

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

Weitere Codebeispiele finden Sie unter NavEntryDecorator.