Вы можете предоставить дополнительную информацию или применить ту же логику к пунктам назначения с помощью класса NavEntryDecorator. Этот класс оборачивает каждый элемент NavEntry в обратном стеке с помощью composable-функции. Иными словами, он украшает контент записи.
Как создать собственный декоратор
Чтобы создать декоратор, расширьте класс NavEntryDecorator и переопределите следующие методы:
decorate– composable-функция, которая вызывается для каждого элементаNavEntryв обратном стеке. Она получаетNavEntryв качестве параметра. Это позволяет создавать объекты состояния, привязанные кcontentKeyзаписи. Вы можете использоватьCompositionLocalProvider, чтобы предоставить зависимости для контента записи. Вы также можете окружить контент composable-функцией или запустить побочные эффекты. Внутри этого метода всегда нужно вызыватьentry.Content().onPop– обратный вызов, который активируется, когдаNavEntryудаляется из обратного стека и покидает композицию. Она получаетcontentKeyудаленной записи. ИспользуйтеcontentKey, чтобы определить и удалить все состояния, связанные с этой записью.
В следующем примере класс NavEntryDecorator расширяется для создания пользовательского декоратора.
// 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") } )
Если декоратору нужен доступ к состоянию, создайте composable-функцию, которая создает это состояние, а затем используйте ее для создания декоратора. Пример реализации можно найти в исходном коде rememberSaveableStateHolderNavEntryDecorator. Это создает состояние – SaveableStateHolder – и использует его для создания декоратора.
Как украсить обратный стек
Создав NavEntryDecorator, вы можете оформить записи в обратном стеке одним из двух способов:
- используйте директиву
rememberDecoratedNavEntries. Эта функция полезна, когда у вас есть несколько обратных стеков, каждый из которых имеет собственный набор декораторов (дополнительную информацию см. в этом рецепте кода). Функция возвращает декорированный списокNavEntry, который можно использовать сNavDisplay. - Передайте декоратор непосредственно в
NavDisplayс помощью параметраentryDecorators.NavDisplayвызываетrememberDecoratedNavEntriesи показывает записи с дополнительной информацией.
Включить декоратор по умолчанию
В Navigation 3 есть декоратор по умолчанию SaveableStateHolderNavEntryDecorator, который позволяет сохранять состояние NavEntry при изменении конфигурации и завершении процесса. Он оборачивает контент NavEntry в SaveableStateProvider, что позволяет вызовам rememberSaveable внутри контента NavEntry работать правильно.
Если ваш декоратор не предоставляет SaveableStateProvider, вам следует включить SaveableStateHolderNavEntryDecorator в качестве первого декоратора в список предоставляемых декораторов. Оно создано с помощью rememberSaveableStateHolderNavEntryDecorator.
Пример:
// import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator NavDisplay( entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), remember { CustomNavEntryDecorator() } ), // ... )
Передача результатов с помощью ResultEventBusNavEntryDecorator
Начиная с Navigation 3 1.2.0, вы можете использовать ResultEventBusNavEntryDecorator, чтобы предоставить ResultEventBus каждому NavEntry с помощью локальной композиции LocalResultEventBus.
По умолчанию rememberResultEventBusNavEntryDecorator создает и запоминает собственный экземпляр ResultEventBus, используя rememberResultEventBus. Если вам нужен доступ к шине событий за пределами иерархии декораторов (например, на верхнем уровне приложения), вы можете поднять ResultEventBus, вызвав rememberResultEventBus и передав его в rememberResultEventBusNavEntryDecorator(resultEventBus):
val resultEventBus = rememberResultEventBus() NavDisplay( /* ... */ entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), rememberResultEventBusNavEntryDecorator(resultEventBus = resultEventBus) ) )
Подробнее о том, как отправлять и отслеживать результаты…
Когда использовать декоратор
Используйте декоратор, чтобы:
- Создайте зависимость для каждого элемента
NavEntryв обратном стеке. Например,ViewModelStoreNavEntryDecoratorсоздаетViewModelStoreдля каждогоNavEntry. - Передавайте результаты и обменивайтесь данными между целевыми страницами. Например,
ResultEventBusNavEntryDecoratorпредоставляетResultEventBusдля пунктов назначения в обратном стеке. - Объект может относиться к нескольким
NavEntry. Например, чтобы использовать один и тот же элементViewModelв нескольких записях. - Выполните одно и то же действие для нескольких объектов типа "
NavEntry". Например, для ведения журнала, отладки или трассировки каждой записи. - Оберните
NavEntryв одну и ту же composable-функцию. - Очистить состояние, связанное с
NavEntry. Например, когда запись удаляется из обратного стека,ViewModelStoreNavEntryDecoratorочищает связанный с нейViewModelStore.
Не используйте декораторы, чтобы:
- Передайте зависимость в один
NavEntry. - Предоставляйте зависимости, область действия которых шире, чем обратный стек.
В обоих случаях передавайте зависимость напрямую при создании NavEntry.
Другие примеры кода можно найти в NavEntryDecorator.