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

HiltViewModel中mutableStateOf更新后@Composable无响应问题

核心问题

你的自定义Loading组件内部使用remember { mutableStateOf(state) }定义的showDialog变量仅会在组件首次渲染时用传入的初始state赋值,后续外部传入的state参数发生变化时,内部的showDialog不会自动同步更新,这就是ViewModel中loading更新后页面没有变化的根本原因。

修复方案

方案1(优先推荐):移除Loading组件内部冗余的状态维护,直接受控于外部传入的状态

Loading的显隐逻辑本身由ViewModel的loading状态控制,内部不需要额外维护独立状态,调整代码如下:

@Composable
fun Loading(state:Boolean, onDismiss: () -> Unit) {
    if(state){
        Dialog(onDismissRequest = onDismiss, DialogProperties(
            dismissOnBackPress = false,dismissOnClickOutside = false
        )) {
            Box(
                modifier = Modifier.size(100.dp).background(Color.White, shape = RoundedCornerShape(8.dp)),
                contentAlignment= Alignment.Center,
            ){
                CircularProgressIndicator()
            }
        }
    }
}

调用处同步修改:

// LoginScreen中调用
Loading(state = loading, onDismiss = { viewModel.loading.value = false })

方案2:保留内部状态,新增外部参数同步逻辑

如果业务需要在Loading内部维护独立状态(比如支持内部关闭后不直接同步外部状态的特殊场景),新增状态同步逻辑即可:

@Composable
fun Loading(state:Boolean, onDismiss: () -> Unit) {
    var showDialog by remember { mutableStateOf(state) }
    // 监听外部state变化,同步更新内部状态
    LaunchedEffect(state) {
        showDialog = state
    }

    if(showDialog){
        Dialog(onDismissRequest = { 
            showDialog = false
            onDismiss()
        }, DialogProperties(
            dismissOnBackPress = false,dismissOnClickOutside = false
        )) {
            Box(
                modifier = Modifier.size(100.dp).background(Color.White, shape = RoundedCornerShape(8.dp)),
                contentAlignment= Alignment.Center,
            ){
                CircularProgressIndicator()
            }
        }
    }
}
可选优化建议

调整ViewModel中的状态定义为读写分离,避免外部直接修改状态,更符合单向数据流规范:

@HiltViewModel
class AuthenticationViewModel @Inject constructor(
    private val repository: AppRepository,
    application: Application
): ViewModel() {
    // 内部可写的私有状态
    private val _loading = mutableStateOf(false)
    // 对外暴露的只读状态
    val loading: State<Boolean> = _loading

    fun update() = viewModelScope.launch {
        _loading.value = true
    }

    // 封装关闭loading的方法,避免外部直接操作状态
    fun dismissLoading() {
        _loading.value = false
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:24:06