Configure your app with metadata

In Navigation 3, you use metadata to share arbitrary information between different library components such as NavEntry, Scene, and NavDisplay. At its most basic, metadata is a Map<String, Any>. However, the library provides additional abstractions to make reading and writing metadata simpler and more type-safe.

Provide NavEntry metadata

If your app builds its NavEntry instances directly, you provide metadata for the entry using the metadata constructor parameter:

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

If your app uses the entryProvider DSL, you provide metadata through the metadata parameter of the entry function. There are two overloads of this function: one that takes a map directly and another that takes a lambda that passes the entry's key as an argument:

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

Provide Scene metadata

By default, Scene.metadata uses a custom getter that returns the metadata of the last entry in its entries property, or an empty map if that is null. When implementing the Scene interface, you can override this default behavior as needed.

Use the metadata DSL

Introduced in the 1.1.0-beta01 release of the library, the metadata domain-specific language (DSL) provides a type-safe builder for creating the Map<String, Any> used to store metadata.

Define metadata keys

The DSL relies on the NavMetadataKey interface to keep the type of the value associated with a metadata key consistent.

The convention for defining metadata keys is to include them as nested objects of the class—or, in the case of functions or composables, a related object—that will read the values associated with those keys:

// 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>
}

Build metadata using the DSL

To create a metadata map, use the metadata function, which takes a lambda parameter. Within this lambda, use the put function to add entries to the map using a NavMetadataKey and corresponding value.

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!")
        }
    }
) {
    // ...
}

Read metadata using metadata keys

The metadata DSL also provides functions to simplify reading metadata with a NavMetadataKey.

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

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