如何防止 Jetpack Compose 中不必要的重组
2021-08-03
12216
我有一个用于搜索查询的
TextField
和一个将执行搜索的
Button
,结果显示在一列中。由于搜索需要几秒钟才能运行,我希望它在按下按钮时执行,而不是在文本更改时执行。
这是一个简化的演示:
Column {
val list = remember { mutableStateListOf<String>() }
val textFieldValue = remember { mutableStateOf(TextFieldValue("")) }
TextField(
value = textFieldValue.value,
onValueChange = { textFieldValue.value = it }
)
Button({
list.clear()
list.addAll(textFieldValue.value.text.split(""))
}) {
Text("Search")
}
list.forEach {
println("test")
Text(it)
}
}
第一次按下按钮后,foreach 循环将在文本更改时运行。即使单击
TextField
也会重新运行循环。这不会在文本更改时运行搜索,但会重新呈现结果,这会导致在文本字段中键入时出现故障。
如何防止这种情况?
3个回答
以上内容适用于 Jetpack Compose。作者想了解 Compose Desktop,但它还不是一样,因为它处于 alpha 阶段,尚未进行太多优化。
修改
mutableState
值始终会导致所有视图重组,并读取其值。
对值的任何更改都将安排读取值的任何可组合函数的重组。
文档
阻止它的方法是将所有读取
mutableState
值的视图移出到单独的视图中。每次
mutableState
值更改时,它都会重新组合,但不会影响容器。
对于您来说,这非常简单:只需移动
TextField
并将
textFieldValue
传递到新函数中即可。您可以转发所需的所有参数,例如
modifier
、
textStyle
等。
@Composable
fun TestView(
) {
Column {
val textFieldValue = remember { mutableStateOf(TextFieldValue("")) }
val list = remember { mutableStateListOf<String>("test") }
TextField(textFieldValue)
Button({
list.clear()
list.addAll(textFieldValue.value.text.split(""))
}) {
Text("Search")
}
list.forEach {
println("test $it")
Text(it)
}
}
}
@Composable
fun TextField(
textFieldValue: MutableState<TextFieldValue>,
) {
TextField(
value = textFieldValue.value,
onValueChange = { textFieldValue.value = it }
)
}
我不确定为什么没有具有这种语义的系统函数,但在 Compose 中,他们更喜欢 状态提升 模式来匹配 UDF。
Phil Dukhov
2021-08-04
我不喜欢移动
mutableState&lt;&gt;
作为参数
就像我一样切勿使用
livedata&lt;&gt;
作为参数。相反,您可以将阅读变成lambda:
520001321
Jemshit
2021-09-12
Column {
val list = remember { mutableStateListOf<String>() }
var textFieldValue = remember { mutableStateOf(TextFieldValue("")) }
var searchTerm = remember { textFieldValue.value.text.copy() }
TextField(
value = textFieldValue.value,
onValueChange = { textFieldValue.value = it }
)
Button({
searchTerm = textFieldValue.value.text.copy()
list.clear()
list.addAll(searchTerm.text.split(""))
}) {
Text("Search")
}
list.forEach {
println("test")
Text(it)
}
}
试试这个
Richard Onslow Roper
2021-08-03