You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在非@Composable函数中修改HomeUiState的日志状态?

问题解决步骤

首先,你遇到的报错根源不是appendLog函数本身,而是connectWithPrivateKey的默认参数里用了viewModel()——这个函数是**@Composable标记的**,只能在Composable函数内部调用,非Composable函数里不能这么用。另外你的HomeUiState设计也有问题,StringBuilder是可变对象,会导致StateFlow无法正确感知状态变化。

1. 修正HomeUiState的不可变性

把logs的类型从StringBuilder改成String,因为数据类应该用不可变类型来保证状态更新的可追溯性:

data class HomeUiState(
    val logs: String = "",
    // 其他字段...
)

2. 调整appendLog函数逻辑

基于不可变的String来拼接日志,确保每次更新都是生成新的状态对象:

class HomeViewModel: ViewModel() {
    private val _homeUiState = MutableStateFlow(HomeUiState())
    val homeUiState: StateFlow<HomeUiState> = _homeUiState.asStateFlow()

    fun appendLog(message: String){
        _homeUiState.update { currentState ->
            currentState.copy(
                logs = currentState.logs + "\n$message"
            )
        }
    }
    // 其他方法...
}

3. 修改connectWithPrivateKey函数

去掉默认参数里的viewModel()调用,改为让调用方传入ViewModel实例——不管是Composable还是非Composable函数,只要能拿到ViewModel的实例就能调用:

fun connectWithPrivateKey(
    host: String,
    username: String,
    homeViewModel: HomeViewModel
) {
    // 在这里可以正常调用appendLog
    homeViewModel.appendLog("开始连接: $host")
    // 其他连接逻辑...
}

如果是在Composable函数里调用connectWithPrivateKey,直接传入viewModel()获取的实例即可:

@Composable
fun HomeScreen() {
    val viewModel: HomeViewModel = viewModel()
    Button(onClick = {
        connectWithPrivateKey("192.168.1.1", "admin", viewModel)
    }) {
        Text("连接")
    }
}

这样调整后,非Composable函数里只要持有HomeViewModel的实例,就能正常调用appendLog修改日志状态,不会再触发Composable相关的报错。

内容的提问来源于stack exchange,提问作者Mioshek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 05:33:13