当我使用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}")
}
}
我发现了一个变通方法是使用currentRecomposable
强制重组,也许有更好的方法,请告诉我。
这里的组合local是转移注意力。由于CCD_ 2是不可观测的,因此组合物没有被通知其改变。最简单的更改是将GlobalState
的定义修改为
class GlobalState(count: Int) {
var count by mutableStateOf(count)
}
这将自动通知撰写count
的值已更改。
我不知道您为什么以这种方式使用compositionLocalOf
。
使用状态提升模式,您可以在组合中使用两个参数:
value: T
:要显示的当前值onValueChange: (T) -> Unit
:请求值更改的事件,其中T是建议的新值
在您的情况下:
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
,并分别提供getter和setter,或者直接提供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())
}
}
}