CompositionLocal позволяет объявлять состояние на самом высоком уровне, а затем получать к нему доступ на любых нижних уровнях без необходимости передавать состояние через промежуточные дочерние элементы. Подобная организация позволяет сделать доступным состояние для определенных веток дереава компонентов.
Объявление состояния с использованием CompositionLocal
начинается с создания объекта ProvidableCompositionLocal, который можно получить с
помощью вызова функции compositionLocalOf() или staticCompositionLocalOf(). В каждом случае функция принимает лямбда-выражение,
которое определяет для состояния значение по умолчанию (если состоянию не передается конкретное значение). Например:
val LocalState1 = compositionLocalOf { значение } val LocalState2 = staticCompositionLocalOf { значение }
Функция staticCompositionLocalOf() рекомендуется для хранения состояния, которое вряд ли будет меняться очень часто. Это связано с тем, что любые изменения состояния приведут к перекомпоновке всей ветки дерева компонентов, для которой определяется состояние. Функция compositionLocalOf() применяется при работе с состояниями, которые часто меняются - она вызывает рекомпозицию только тех компонентов, которые обращаются к состоянию.
Далее в вызове CompositionLocalProvider объекту ProvidableCompositionLocal
передается некоторое значение с помощью слова provides,
и выполняется вызов непосредственного дочернего компонента:
CompositionLocalProvider(LocalState1 provides новое_значение) { ChildComposable() }
В итоге любые вложенные компоненты внутри компонента ChildComposable будут иметь прямой доступ к состоянию CompositionLocal через свойство current объекта ProviderCompositionLocal:
val переменная = LocalState1.current
Рассмотрим простейший пример:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Column import androidx.compose.material3.Text import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Column { Composable11() // изменяем состояние для подветки компонента Composable21 CompositionLocalProvider(LocalMessage provides "World") { Composable21() } } } } } // локальное состояние val LocalMessage = staticCompositionLocalOf { "Hello" } @Composable fun Composable21(){ Composable22() } // получаем состояние @Composable fun Composable22(){ Text(LocalMessage.current, fontSize = 28.sp) } @Composable fun Composable11(){Composable12()} @Composable fun Composable12(){ Text(LocalMessage.current, fontSize = 28.sp)}
Здесь на верхнем уровне определено состояние LocalMessage (название произвольное):
val LocalMessage = staticCompositionLocalOf { "Hello" }
В методе setContent вызываем два компонента Composable11 и Composable21. Причем для второго компонента (и соответственно для всех его дочерних компонентов) переустанавливаем значение состояния:
Column { Composable11() CompositionLocalProvider(LocalMessage provides "World") { Composable21() } }
После этого во вложенных компонентах через LocalMessage.current
можно получить состояние:
@Composable fun Composable22(){ Text(LocalMessage.current, fontSize = 28.sp) } @Composable fun Composable12(){ Text(LocalMessage.current, fontSize = 28.sp)}