使用元数据配置应用

在 Navigation 3 中,您可以使用元数据在不同的库组件(例如 NavEntrySceneNavDisplay)之间共享任意信息。从最基本的层面来说,元数据就是 Map<String, Any>。不过,该库提供了额外的抽象层,可让元数据的读取和写入更简单且更具类型安全性。

提供 NavEntry 元数据

如果您的应用直接构建 NavEntry 实例,您可以使用 metadata 构造函数参数为条目提供元数据:

when (key) {
    is Home -> NavEntry(key, metadata = mapOf("key" to "value")) {}
}

如果您的应用使用 entryProvider DSL,您可以通过 entry 函数的 metadata 参数提供元数据。此函数有两个重载版本:一个直接接受映射,另一个接受将条目的键作为实参传递的 lambda:

entry<Home>(metadata = mapOf("key" to "value")) { /* ... */ }
entry<Conversation>(metadata = { key: Conversation ->
    mapOf("key" to "value: ${key.id})")
}) { /* ... */ }

提供 Scene 元数据

默认情况下,Scene.metadata 使用自定义 getter,该 getter 会返回其 entries 属性中最后一个条目的 metadata,如果该属性为 null,则返回空映射。实现 Scene 接口时,您可以根据需要替换此默认行为。

使用元数据 DSL

元数据领域特定语言 (DSL) 在库的 1.1.0-beta01 版本中引入,提供了一个类型安全的构建器,用于创建用于存储元数据的 Map<String, Any>

定义元数据键

该 DSL 依赖于 NavMetadataKey 接口来保持与元数据键关联的值的类型一致。

定义元数据键的惯例是将它们作为类的嵌套对象(或在函数或可组合项的情况下,作为将读取与这些键关联的值的相关对象)包含在内:

// For classes such as scene strategies or nav entry decorators, you can define the keys
// as nested object.
class MySceneStrategy<T : Any> : SceneStrategy<T> {

    // ...

    object MyStringMetadataKey : NavMetadataKey<String>
}

// An example from NavDisplay.
// Because NavDisplay is a function, the metadata keys are defined in an object with the same name.
public object NavDisplay {

    public object TransitionKey :
        NavMetadataKey<AnimatedContentTransitionScope<Scene<*>>.() -> ContentTransform>
}

使用 DSL 构建元数据

如需创建元数据映射,请使用 metadata 函数,该函数接受一个 lambda 参数。在此 lambda 中,使用 put 函数,通过 NavMetadataKey 和相应的值向映射添加条目。

entry<Home>(
    metadata = metadata {
        put(NavDisplay.TransitionKey) { fadeIn() togetherWith fadeOut() }
        // An additional benefit of the metadata DSL is the ability to use conditional logic
        if (condition) {
            put(MySceneStrategy.MyStringMetadataKey, "Hello, world!")
        }
    }
) {
    // ...
}

使用元数据键读取元数据

元数据 DSL 还提供了一些函数,可用于简化通过 NavMetadataKey 读取元数据的过程。

// import androidx.navigation3.runtime.contains
// import androidx.navigation3.runtime.get

val hasMyString: Boolean = metadata.contains(MySceneStrategy.MyStringMetadataKey)
val myString: String? = metadata[MySceneStrategy.MyStringMetadataKey]