Как настроить приложение с помощью метаданных

В Navigation 3 метаданные используются для передачи произвольной информации между разными компонентами библиотеки, например NavEntry, Scene и NavDisplay. В самом простом случае метаданные – это Map<String, Any>. Однако библиотека предоставляет дополнительные абстракции, чтобы упростить чтение и запись метаданных и сделать их более безопасными с точки зрения типов.

Добавьте метаданные NavEntry

Если ваше приложение создает экземпляры NavEntry напрямую, вы можете указать метаданные для записи, используя параметр конструктора metadata:

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

Если в вашем приложении используется DSL entryProvider, метаданные передаются с помощью параметра metadata функции entry. У этой функции две перегрузки: одна принимает карту напрямую, а другая – лямбда-функцию, которая передает ключ записи в качестве аргумента:

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

Добавьте метаданные Scene

По умолчанию в Scene.metadata используется специальный геттер, который возвращает metadata последнего элемента в свойстве entries или пустую карту, если это null. При реализации интерфейса Scene вы можете переопределить это поведение по умолчанию.

Как использовать DSL метаданных

Представленный в версии 1.1.0-beta01 библиотеки язык описания домена (DSL) для метаданных предоставляет безопасный с точки зрения типов конструктор для создания 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. В этой лямбда-функции используйте функцию 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]