CompositionLocal

Последнее обновление: 04.04.2024

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)}
Состояние CompositionLocal и его передача в дочерние компоненты в Jetpack Compose в Kotlin на Android
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850