Hel*_*oCW 3 kotlin android-jetpack-compose
我已经阅读了一些学习 Compose 的示例代码。
我发现很多示例项目都使用代码A创建StateFlowin视图模型,然后将其转换为Statein@Composable函数,UI会在drawerOpen更改时自动更新。
1:我认为Code B和Code C都可以做同样的事情,对吧?为什么很多项目很少使用它们?
2:代码A是个好方法吗?
3:我不需要添加rememberSaveable变量drawerOpen,@Composable fun myRoute(...)因为视图模型将存储数据,对吧?
代码A
class MainViewModel : ViewModel() {
private val _drawerShouldBeOpened = MutableStateFlow(false)
val drawerShouldBeOpened: StateFlow<Boolean> = _drawerShouldBeOpened
...
}
@Composable
fun myRoute(
val drawerOpen by MainViewModel.drawerShouldBeOpened.collectAsState() //Do I need add rememberSaveable ?
...
}
Run Code Online (Sandbox Code Playgroud)
代码B
class MainViewModel : ViewModel() {
private val _drawerShouldBeOpened = mutableStateOf(false)
val drawerShouldBeOpened: State<Boolean> = _drawerShouldBeOpened
...
}
@Composable
fun myRoute(
val drawerOpen = MainViewModel.drawerShouldBeOpened //Do I need add rememberSaveable ?
...
}
Run Code Online (Sandbox Code Playgroud)
代码C
class MainViewModel : ViewModel() {
private var _drawerShouldBeOpened = false
val drawerShouldBeOpened: Boolean = _drawerShouldBeOpened
...
}
@Composable
fun myRoute(
val drawerOpen = rememberSaveable { mutableStateOf(MainViewModel.drawerShouldBeOpened)) //Can I remove rememberSaveable ?
}
Run Code Online (Sandbox Code Playgroud)
这里有多个问题。
让我回答一切可能的问题。
1. 你应该在哪里使用remember/ rememberSaveable?(代码 A、B 或 C)
仅在代码 C 中需要它。
(在代码A和B中使用也没有问题,但没有优势)
原因,
在代码 A 和 B 中 - 状态保存在视图模型中。因此,该值在重组后仍然存在。
但在代码 C 中,状态是在可组合项内部创建和维护的。因此,remember需要使值能够在重组中幸存下来。
2. 为什么Code C用得不多?
只要状态(而不是值)发生变化,就会发生可组合重组。
下面给出了一个简单的例子来证明这一点。
class ToggleViewModel : ViewModel() {
private val _enabledStateFlow = MutableStateFlow(false)
val enabledStateFlow: StateFlow<Boolean> = _enabledStateFlow
private val _enabledState = mutableStateOf(false)
val enabledState: State<Boolean> = _enabledState
private var _enabled = false
val enabled: Boolean = _enabled
fun setEnabledStateFlow(isEnabled: Boolean) {
_enabledStateFlow.value = isEnabled
}
fun setEnabledState(isEnabled: Boolean) {
_enabledState.value = isEnabled
}
fun setEnabled(isEnabled: Boolean) {
_enabled = isEnabled
}
}
@Composable
fun BooleanToggle(
viewmodel: ToggleViewModel = ToggleViewModel(),
) {
val enabledStateFlow by viewmodel.enabledStateFlow.collectAsState()
val enabledState by viewmodel.enabledState
val enabled by rememberSaveable {
mutableStateOf(viewmodel.enabled)
}
Column {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
) {
Text(text = if (enabledStateFlow) {
"Enabled"
} else {
"Disabled"
})
Button(onClick = { viewmodel.setEnabledStateFlow(!enabledStateFlow) }) {
Text("Toggle State Flow")
}
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
) {
Text(text = if (enabledState) {
"Enabled"
} else {
"Disabled"
})
Button(onClick = { viewmodel.setEnabledState(!enabledState) }) {
Text("Toggle State")
}
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
) {
Text(text = if (enabled) {
"Enabled"
} else {
"Disabled"
})
Button(onClick = { viewmodel.setEnabled(!enabled) }) {
Text("Toggle Value")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以看到,单击按钮后第三个文本不会更新。
原因是可组合项内的可变状态是使用视图模型数据中的初始值创建的。但对该数据的进一步更新不会反映在可组合项中。
为了获取更新,我们必须使用反应性数据,例如Flow、LiveData、State及其变体。
3. 使用StateFlowvs State。
从文档中,您可以看到 compose 支持Flow,LiveData和RxJava。
collectAsState()您可以在我们使用for的用法中看到StateFlow。该方法转换StateFlow为State. 所以两者都可以使用。
Flow如果超出的层ViewModel(如存储库)是数据源并且它们使用数据类型,则使用Flow。
其他MutableState应该没问题。
| 归档时间: |
|
| 查看次数: |
5610 次 |
| 最近记录: |