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

ViewModel更新未触发Jetpack Compose重组问题求助

问题修复:Compose点击刷新不显示loading状态

问题原因

你的ProductUiState使用var修饰内部属性,直接修改productUiState.status = "loading"时,只是修改了现有对象的内部值,而mutableStateOf仅监测对象引用的变化,所以这次修改不会触发Compose重组,导致loading状态无法更新。后续协程中重新赋值productUiState = ProductUiState(...)是创建了新对象,引用发生变化,因此能触发重组显示新数据。

修复步骤

  1. 将ProductUiState改为不可变数据类,用val替代var,强制通过创建新对象更新状态
  2. 修改getProducts方法,通过新对象设置loading状态,确保触发重组

修改后的代码

ViewModel代码

data class ProductUiState(
    val status: String,
    val products: List<Product>?
)

class ProductViewModel : ViewModel() {
    var productUiState: ProductUiState by mutableStateOf(
        ProductUiState(
            status = "loading",
            products = null
        )
    )

    init {
        getProducts()
    }

    fun getProducts() {
        // 创建新的loading状态对象,触发重组
        productUiState = productUiState.copy(status = "loading")
        viewModelScope.launch {
            productUiState = try {
                val listResult = POSApi.retrofitService.getProducts()
                ProductUiState("done", listResult)
            } catch (e: IOException) {
                ProductUiState("error", listOf())
            }
        }
    }
}

Composable代码(无需修改)

fun Shop() {
    val productViewModel: ProductViewModel = viewModel()

    Column() {
        val productUiState = productViewModel.productUiState

        Text(productUiState.status)

        when (productUiState.status) {
            "loading" -> LoadingImage()
            "done" -> Text(productUiState.products?.size.toString())
        }

        Button(onClick = { productViewModel.getProducts() }) {
            Text("Reload")
        }
    }
}

额外优化建议

  • 用枚举类替代字符串表示status,避免拼写错误,提升代码安全性:
enum class UiStatus { LOADING, DONE, ERROR }

将ProductUiState中的status类型改为UiStatus,后续判断状态时直接使用枚举值即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 23:30:12