В отличие от CompositionLocalOf, чтение staticCompositionLocalOf не отслеживается композитором и не меняет значение, указанное в CompositionLocalProvider > вызов приведет к перекомпоновке всего содержимого, а не только тех мест, где в композиции используется локальное значение.
Запуск прикрепленного кода , я ожидал, что компонуемый текст как в setContent, так и в компонуемом Node, а также сам компонуемый Node будет перекомпонован, когда я нажму кнопку. Однако инспектор слоев Android Studio показал, что были перекомпонованы только Leaf и Text, которые можно компоновать в Leaf. Как видно на прилагаемых снимках экрана, изменение staticCompositionLocalOf во второй строке кода на CompositionLocalOf привело к тем же рекомпозициям. Я также попробовал counter = mutableStateOf(Counter()) с соответствующим образом обновленным типом LocalCounter, без каких-либо различий в результатах.


Код: Выделить всё
data class Counter (var count: MutableState = mutableStateOf(0))
val LocalCounter = staticCompositionLocalOf {
error("CompositionLocal LocalCounter not provided")
}
class MainActivity : ComponentActivity() {
private var counter = Counter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CompositionLocalProvider(LocalCounter provides counter) {
Column {
Text("setContent ${LocalCounter}")
Node()
Button(content = { Text("+1") },
onClick = { counter.count.value += 1 }
)
}
}
}
}
}
@Composable
fun Node() {
Text("Node")
Leaf()
}
@Composable
fun Leaf() {
val counter = LocalCounter.current
Text("Leaf count: ${counter.count.value}")
}
Связанные вопросы о stackoverflow и Интернете в целом чаще всего задаются об использовании CompositionLocal, например, как и когда именно CompositionLocal устанавливает значения неявно? или https://stackoverflow.com/a/77496284, или о концептуальной разнице между staticCompositionLocalOf и CompositionLocalOf, которую объясняет официальная документация. Мне не удалось найти ни одного примера кода, показывающего, как можно показать разницу между этими двумя.
Ни одного примера, показывающего рекомпозицию составных элементов, которые не поддерживаются. используйте предоставленное значение, но исключительно из-за использования staticCompositionLocalOf, мы будем очень признательны!
Обновленный код на основе ответа Яна Итора:< /strong>
В одной из моих первоначальных неудачных попыток вместо наблюдения за предоставленным значением типа Counter я пытался просмотреть предоставленное значение типа MutableState и обновление счетчика в изменяемом значении при нажатии кнопки. Вот различия с неизменяемым свойством в классе данных:
Код: Выделить всё
# line 1:
data class Counter(var count: Int = 0)
# line 2:
val LocalCounter = staticCompositionLocalOf {
# line 6:
private var counter = mutableStateOf(Counter())
# line 18:
onClick = { counter.value = Counter(counter.value.count + 1) }
# line 35:
Text("Leaf count: ${counter.value.count}")
Чтобы увидеть эффект staticCompositionLocalOf, необходимо изменить значение внутри самого поля CompositionLocal. Вот обновленный код:
Код: Выделить всё
data class Counter(var count: Int = 0)
val LocalCounter = staticCompositionLocalOf {
error("CompositionLocal LocalCounter not provided")
}
class MainActivity : ComponentActivity() {
private var counter = mutableStateOf(Counter())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CompositionLocalProvider(LocalCounter provides counter.value) {
Column {
Text("setContent ${LocalCounter}")
Node()
Button(content = { Text("+1") },
onClick = { counter.value = Counter(counter.value.count + 1) }
)
}
}
}
}
}
@Composable
fun Node() {
Text("Node")
Leaf()
}
@Composable
fun Leaf() {
val counter = LocalCounter.current
Text("Leaf count: ${counter.count}")
}

Чтобы уточнить официальную документацию, я хочу сказать, что если наблюдаемое изменяемое состояние является членом класса, но экземпляр класса, предоставленный CompositionLocal, сам по себе не является измениться, использование staticCompositionLocalOf предотвращает отслеживание предоставленного (неизмененного) экземпляра. С другой стороны, если сам предоставленный экземпляр изменяется, использование композицииLocalOf предотвращает повторную композицию компонуемых объектов, не учитывающих предоставленный экземпляр. Примеры первого: исходный Counter выше или коллекции, в которых отдельные элементы являются изменяемыми и наблюдаемыми, но сами экземпляры коллекций неизменны. Примеры последнего: замена целых экземпляров базовых типов, String, коллекций или пользовательских классов.
Подробнее здесь: https://stackoverflow.com/questions/785 ... ionlocalof
Мобильная версия