我正在做一个项目,遇到了一个问题。这是下面代码中我的问题的最小示例,当文本更改时,TextField 应该仅重新组合。但它重构了整个可组合函数。为什么以及如何处理?
@Composable
fun RecompositionPractice() {
var text by remember {
mutableStateOf("")
}
Box {
TextField(value = text, onValueChange = { text = it })
}
}
这是我面临同样问题的另一个代码示例。在下面的代码中,
TextField
也应该重组,但CustomField
也在重组。
@Composable
fun MainScreenContent() {
var userName by remember {
mutableStateOf("")
}
CustomField(value = userName, onValueChange = { userName = it })
}
@Composable
fun CustomField(
value: String,
onValueChange: (String) -> Unit
) {
TextField(
label = { Text(text = "Enter Your Name") },
value = value,
onValueChange = { onValueChange(it) }
)
}
请提供两个代码示例的解决方案。
我想说你的代码完全没问题,你只需要理解为什么它是这样的。
每次在其内部读取的可变状态发生更改时,Composable 都会重新组合,这也会导致子级的重新组合(但不使用更改后的可变状态的子级的重新组合将被跳过)。例如,如果我们稍微包装一下您的代码:
@Composable
fun MainContent1() {
MainContent2()
}
@Composable
fun MainContent2() {
var userName by remember {
mutableStateOf("")
}
MainScreenContent3(userName, onValueChange = { userName = it })
}
@Composable
fun MainScreenContent3(
value: String,
onValueChange: (String) -> Unit
) {
CustomField(value = value, onValueChange = onValueChange)
}
MainContent1 不会被重组,但是 MainContent2 和 MainContent3 以及 CustomField(MainContent2 的子级)将被重组,因为 MainContent2 读取已更改的可变状态。 减少组合的方法是将用户名移至可组合项中更深的位置,因此如果代码如下所示:
@Composable
fun MainContent1() {
MainContent2()
}
@Composable
fun MainContent2() {
MainScreenContent3()
}
@Composable
fun MainScreenContent3(
) {
var userName by remember {
mutableStateOf("")
}
CustomField(value = userName, onValueChange = { userName = it })
}
现在 MainContent1 和 MainContent2 不会被重构,但 MainContent3 会被重构。完成同样事情的其他选择是传递 MutableState,但请注意,这并不是真正的最佳解决方案:
@Composable
fun MainContent1() {
MainContent2()
}
@Composable
fun MainContent2() {
val userName = remember { mutableStateOf("") }
MainScreenContent3(userName)
}
@Composable
fun MainScreenContent3(
value: MutableState<String>
) {
CustomField(value = value.value, onValueChange = { value.value = it })
}
但是您应该检查是否有两个这样的文本字段:
@Composable
fun MainScreenContent() {
var userName by remember {
mutableStateOf("")
}
var userName2 by remember {
mutableStateOf("")
}
Column {
CustomField(value = userName, onValueChange = { userName = it })
CustomField(value = userName2) { userName2 = it }
}
}
在一个字段中输入一些内容,您会期望跳过其他字段的重组,情况应该是这样,并且它应该看起来像这样。可以看到MainContent被重构了,还有一个CustomField,但是其他字段的重构被跳过了。
希望这对您有帮助,并且您现在就知道重组会发生什么。