Как вызвать перекомпоновку при изменении родительских данных с помощью CompositionLocal
когда я использую CompositionLocal, я получаю данные от родителя и изменяю их, но обнаружил, что это не вызовет перекомпоновку потомков.
Я успешно изменил данные, что подтверждается тем, что когда я добавляю дополнительное состояние в дочерний компонент, а затем изменяю его, чтобы инициировать перекомпоновку, я могу получить новые данные.
Кто-нибудь может мне помочь?
Добавить
код, как показано ниже
data class GlobalState(var count: Int = 0)
val LocalAppState = compositionLocalOf { GlobalState() }
@Composable
fun App() {
CompositionLocalProvider(LocalAppState provides GlobalState()) {
CountPage(globalState = LocalAppState.current)
}
}
@Composable
fun CountPage(globalState: GlobalState) {
// use it request recomposition worked
// val recomposeScope = currentRecomposeScope
BoxWithConstraints(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
.clickable {
globalState.count++
// recomposeScope.invalidate()
}) {
Text("count ${globalState.count}")
}
}
Я нашел обходной путь, использующий
3 ответа
Композиция "местная" здесь - отвлекающий маневр. С
GlobalScope
не наблюдаемый состав не уведомляется о том, что он изменился. Самое простое изменение - изменить определение
GlobalState
к,
class GlobalState(count: Int) {
var count by mutableStateOf(count)
}
Это автоматически уведомит compose о том, что значение
count
изменилось.
Я не уверен, почему вы используете
compositionLocalOf
этим способом.
Вы можете использовать что-нибудь попроще:
data class GlobalState(var count: Int = 0)
@Composable
fun App() {
var counter by remember { mutableStateOf(GlobalState(0)) }
CountPage(
globalState = counter,
onUpdateCount = {
counter = counter.copy(count = counter.count +1)
}
)
}
@Composable
fun CountPage(globalState: GlobalState, onUpdateCount: () -> Unit) {
BoxWithConstraints(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
.clickable (
onClick = onUpdateCount
)) {
Text("count ${globalState.count}")
}
}
Вы можете объявить свои данные как и либо предоставить отдельно геттер и сеттер, либо просто предоставить
MutableState
объект напрямую.
internal val LocalTest = compositionLocalOf<Boolean> { error("lalalalalala") }
internal val LocalSetTest = compositionLocalOf<(Boolean) -> Unit> { error("lalalalalala") }
@Composable
fun TestProvider(content: @Composable() () -> Unit) {
val (test, setTest) = remember { mutableStateOf(false) }
CompositionLocalProvider(
LocalTest provides test,
LocalSetTest provides setTest,
) {
content()
}
}
Внутри дочернего компонента вы можете сделать:
@Composable
fun Child() {
val test = LocalTest.current
val setTest = LocalSetTest.current
Column {
Button(onClick = { setTest(!test) }) {
Text(test.toString())
}
}
}