最近我在玩 Jetpack Compose,我注意到文本可能不会显示在 TextField 中。
所以我有一个 ViewModel
,其中 Flow
为 ViewState
。
在我的 Compose
文件中,我有类似的内容:
@Composable
internal fun TestScreen() {
val state by viewModel.state.collectAsState()
TestScreen {
viewState = state,
actioner = { ... }
}
}
@Composable
private fun TestScreen(viewState: ViewState, actioner: () -> Unit) {
var name by remember {
mutableStateOf(
TextFieldValue(viewState.name)
)
}
Surface {
....
Column {
....
OutlinedTextField(
...
value = name,
onValueChange = { textFieldValue ->
name = textFieldValue
actioner(...)
}
)
}
}
}
OutlineTextField
永远不会显示 viewState.name
中已有的内容
但是,如果我改变这个:
var name by remember {
mutableStateOf(
TextFieldValue(viewState.name)
)
}
为此:
var name = TextFieldValue(viewState.name)
显然它可以显示 viewState.name
中的值。
根据文档 (https://developer.android.com/jetpack/compose/state#state-in-composables),它建议使用 remember
和 mutableStateOf
来处理更改。
如果有人能帮我解释为什么带有 remember
的代码不起作用但直接分配的值起作用,我将不胜感激?
viewState.name
是一个 String
我通过执行以下操作“部分解决”了这个问题:
var name by remember {
mutableStateOf(
TextFieldValue("")
)
}
name = TextFieldValue(viewState.name)
然后可以显示名称。但看起来不太对劲?
答案 0 :(得分:1)
remember
仅用于确保在重新组合时,mutableStateOf
对象的值不会重新初始化为初始值。
例如
@Composable
fun Test1(){
var text by mutableStateOf ("Prev Text")
Text(text)
Button(onClick = { text = "Updated Text" }){
Text("Update The Text")
}
}
不会在按钮点击时更新文本。这是因为单击按钮会更改 mutableStateOf text
,这将触发重新组合。但是,当控件到达 Composable 的第一行时,它会将变量 text
重新初始化为“Prev Text”。
这就是 remember
的用武之地。
如果你把上面的初始化改成
var text by remember { mutableStateOf ("Prev Text") }
,
它会告诉 compose 跟踪这个变量,并“记住”它的值,并在重新组合时再次使用它,当控件再次到达初始化逻辑时。因此,请记住那里充当“守卫”,不会让控件进入初始化逻辑,并返回它当前存储的变量的最新记忆值。