您可以使用 NavEntryDecorator 类提供额外信息或将相同的逻辑应用于目的地。此类使用可组合函数封装返回堆栈中的每个 NavEntry。换句话说,它会修饰条目的内容。
创建自定义装饰器
如需创建装饰器,请扩展 NavEntryDecorator 类并替换以下方法:
decorate- 一个可组合 lambda,会针对返回堆栈中的每个NavEntry调用。它会接收NavEntry作为参数。这样,您就可以创建以条目的contentKey为键的状态对象。您可以使用CompositionLocalProvider为条目的内容提供依赖项。 您还可以使用可组合函数封装内容,或触发附带效应。您应始终在此方法内调用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") } )
如果修饰器需要访问状态,请创建一个可组合函数来创建该状态,然后使用该状态来构造修饰器。如需查看实现示例,请参阅 rememberSaveableStateHolderNavEntryDecorator 的源代码。这会创建状态(SaveableStateHolder),并使用它来构造修饰器。
修饰返回堆栈
创建 NavEntryDecorator 后,您可以通过以下两种方式之一修饰返回堆栈中的条目:
- 使用
rememberDecoratedNavEntries。当您有多个返回堆栈且每个返回堆栈都有自己的一组修饰符时,此函数非常有用(如需了解详情,请参阅此代码方案)。该函数会返回一个修饰过的NavEntry列表,您可以将其与NavDisplay搭配使用。 - 使用
entryDecorators参数直接向NavDisplay提供修饰器。NavDisplay在后台调用rememberDecoratedNavEntries并显示修饰后的条目。
添加默认修饰器
Navigation 3 包含一个名为 SaveableStateHolderNavEntryDecorator 的默认修饰器,该修饰器可让 NavEntry 的状态在配置更改和进程终止后得以保留。它使用 SaveableStateProvider 封装 NavEntry 内容,从而使 NavEntry 内容中的 rememberSaveable 调用能够正常运行。
除非您的装饰器提供 SaveableStateProvider,否则您应将 SaveableStateHolderNavEntryDecorator 作为所提供装饰器列表中的第一个装饰器。它是使用 rememberSaveableStateHolderNavEntryDecorator 创建的。
例如:
// import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator NavDisplay( entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), remember { CustomNavEntryDecorator() } ), // ... )
使用 ResultEventBusNavEntryDecorator 传递结果
从 Navigation 3 1.2.0 开始,您可以使用 ResultEventBusNavEntryDecorator 通过 LocalResultEventBus 组合局部变量为每个 NavEntry 提供 ResultEventBus。
默认情况下,rememberResultEventBusNavEntryDecorator 会在内部使用 rememberResultEventBus 创建并记住自己的 ResultEventBus 实例。如果您需要在修饰符层次结构之外(例如在顶级应用框架中)访问事件总线,可以通过调用 rememberResultEventBus 并将其传递给 rememberResultEventBusNavEntryDecorator(resultEventBus) 来提升 ResultEventBus:
val resultEventBus = rememberResultEventBus() NavDisplay( /* ... */ entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), rememberResultEventBusNavEntryDecorator(resultEventBus = resultEventBus) ) )
如需详细了解如何发送和观察结果,请参阅返回结果。
何时使用修饰器
使用修饰器可以:
- 为返回堆栈中的每个
NavEntry创建一个依赖项。例如,ViewModelStoreNavEntryDecorator会为每个NavEntry创建一个ViewModelStore。 - 在目的地之间传递结果和进行通信。例如,
ResultEventBusNavEntryDecorator为返回堆栈中的目的地提供ResultEventBus。 - 将一个对象限定为多个
NavEntry。例如,在多个条目之间共享ViewModel。 - 对多个
NavEntry执行相同的操作。例如,为每个条目执行日志记录、调试或跟踪操作。 - 使用相同的可组合函数封装
NavEntry。 - 清理与
NavEntry关联的状态。例如,当某个条目从返回堆栈中移除时,ViewModelStoreNavEntryDecorator会清除其关联的ViewModelStore。
请勿使用修饰器执行以下操作:
- 将依赖项传递给单个
NavEntry。 - 提供范围比返回堆栈更广的依赖项。
在这两种情况下,请改为在创建 NavEntry 时直接传递依赖项。
如需查看更多代码示例,请参阅 NavEntryDecorator。