首页 > 解决方案 > Jetpack Compose 在 ViewModel 中观察 mutableStateOf

问题描述

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

  1. 视图模型
class ProfileViewModel : BaseViewModel() {

    var greet = mutableStateOf(user.pushSetting.greet)
    var message = mutableStateOf(user.pushSetting.message)
    var messageDetails = mutableStateOf(user.pushSetting.messageDetails)

    var follow = mutableStateOf(user.pushSetting)
    var like = mutableStateOf(user.pushSetting.like)
    var comment = mutableStateOf(user.pushSetting.comment)

    fun updateUser() {
        println("--")
    }
}

2.可组合

@Composable
fun SettingCard(viewModel: ProfileViewModel) {

    Lists {
        Section {
            TextRow(text = "手机号码") { }
            TextRow(text = "修改密码", line = false) { }
        }

        Section {
            SwitchRow(text = "新好友通知", checkedState = viewModel.greet)
            SwitchRow(text = "新消息通知", checkedState = viewModel.message)
            SwitchRow(text = "消息显示详细", line = false, checkedState = viewModel.messageDetails)
        }
    }
}

3.SwitchRow

@Composable
fun SwitchRow(text: String, line: Boolean = true, checkedState: MutableState<Boolean>) {

    ListItem(
        text = { Text(text) },
        trailing = {
            Switch(
                checked = checkedState.value,
                onCheckedChange = { checkedState.value = it },
                colors = SwitchDefaults.colors(checkedThumbColor = MaterialTheme.colors.primary)
            )
        }
    )
}

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

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

LaunchedEffect(viewModel.greet) {
     viewModel.updateUser()
}

标签: viewmodelandroid-jetpack-compose

解决方案


最好的解决方案是按照@Codecameo 的建议使用 lambda进行单向流。SwitchRow

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

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

init {
    snapshotFlow { greet.value }
        .onEach {
            updateUser()
        }
        .launchIn(viewModelScope)
        //...
}

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


推荐阅读