Jetpack Compose 观察 ViewModel 中的 mutableStateOf

gao*_*way 8 viewmodel android-jetpack-compose

我需要更新用户配置文件开关

\n
    \n
  1. 视图模型
  2. \n
\n
class ProfileViewModel : BaseViewModel() {\n\n    var greet = mutableStateOf(user.pushSetting.greet)\n    var message = mutableStateOf(user.pushSetting.message)\n    var messageDetails = mutableStateOf(user.pushSetting.messageDetails)\n\n    var follow = mutableStateOf(user.pushSetting)\n    var like = mutableStateOf(user.pushSetting.like)\n    var comment = mutableStateOf(user.pushSetting.comment)\n\n    fun updateUser() {\n        println("--")\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

2.可组合性

\n
@Composable\nfun SettingCard(viewModel: ProfileViewModel) {\n\n    Lists {\n        Section {\n            TextRow(text = "\xe6\x89\x8b\xe6\x9c\xba\xe5\x8f\xb7\xe7\xa0\x81") { }\n            TextRow(text = "\xe4\xbf\xae\xe6\x94\xb9\xe5\xaf\x86\xe7\xa0\x81", line = false) { }\n        }\n\n        Section {\n            SwitchRow(text = "\xe6\x96\xb0\xe5\xa5\xbd\xe5\x8f\x8b\xe9\x80\x9a\xe7\x9f\xa5", checkedState = viewModel.greet)\n            SwitchRow(text = "\xe6\x96\xb0\xe6\xb6\x88\xe6\x81\xaf\xe9\x80\x9a\xe7\x9f\xa5", checkedState = viewModel.message)\n            SwitchRow(text = "\xe6\xb6\x88\xe6\x81\xaf\xe6\x98\xbe\xe7\xa4\xba\xe8\xaf\xa6\xe7\xbb\x86", line = false, checkedState = viewModel.messageDetails)\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

3.切换行

\n
@Composable\nfun SwitchRow(text: String, line: Boolean = true, checkedState: MutableState<Boolean>) {\n\n    ListItem(\n        text = { Text(text) },\n        trailing = {\n            Switch(\n                checked = checkedState.value,\n                onCheckedChange = { checkedState.value = it },\n                colors = SwitchDefaults.colors(checkedThumbColor = MaterialTheme.colors.primary)\n            )\n        }\n    )\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如何在ViewModel中观察开关的变化并调用updateUser()

\n

我知道这是一个办法,但是并不理想。每次初始化时都会调用网络更新。有更好的解决方案吗?

\n
LaunchedEffect(viewModel.greet) {\n     viewModel.updateUser()\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Thr*_*ian 22

对此的最佳解决方案是使用 lambda 进行单向流,如 @Codecameo 建议的那样SwitchRow

但是如果你想观察你内部的 MutableStateViewmodel你可以使用snapshotFlows 作为

var greet: MutableState<Boolean> = mutableStateOf(user.pushSetting.greet)

init {
    snapshotFlow { greet.value }
        .onEach {
            updateUser()
        }
        .launchIn(viewModelScope)
        //...
}
Run Code Online (Sandbox Code Playgroud)

从可观察的快照状态创建一个流。(例如 mutableStateOf 返回的状态持有者。) snapshotFlow 创建一个 Flow,该 Flow 在收集时运行块并发出结果,记录访问的任何快照状态。当收集继续时,如果应用了新的快照来更改块访问的状态,则流程将再次运行块,重新记录所访问的快照状态。如果块的结果不等于先前的结果,流程将发出新的结果。(此行为与 Flow.distinctUntilChanged 的​​行为类似。)收集将无限期地继续,除非明确取消或通过使用其他 Flow 运算符进行限制。