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

Kotlin中UI从ViewModel获取数据为null/默认值问题排查

问题根源

你遇到的核心问题是异步操作的执行顺序问题:

  • ViewModel中的getFirstConversionRateByCurrency和getSecondConversionRateByCurrency函数,用viewModelScope.launch启动了异步协程去调用UseCase获取数据,但函数会立刻返回初始的null值——因为协程是后台执行的,还没等UseCase返回数据并赋值给first/second,return语句已经执行完毕了。
解决方案

按照Jetpack Compose + MVVM的响应式设计规范,应该用可观察的状态容器来存储数据,让UI自动感知数据变化,而不是试图同步获取异步结果。

1. 修改ViewModel代码

将first/second替换为Compose支持的MutableState,并将获取数据的函数改为触发式(不返回值,只更新状态):

@HiltViewModel
class ExchangeMainViewModel @Inject constructor(
    private val getConversionRateByCurrencyUseCase: GetConversionRateByCurrencyUseCase
) : ViewModel() {
    // 用MutableState存储汇率数据,Compose可自动观察变化
    val firstRate = mutableStateOf<String?>(null)
    val secondRate = mutableStateOf<String?>(null)

    // 触发获取第一个汇率,更新状态
    fun fetchFirstConversionRate(currency: String) {
        viewModelScope.launch {
            val rate = getConversionRateByCurrencyUseCase.getConversionRateByCurrency(currency)
            firstRate.value = rate?.toString()
        }
    }

    // 触发获取第二个汇率,更新状态
    fun fetchSecondConversionRate(currency: String) {
        viewModelScope.launch {
            val rate = getConversionRateByCurrencyUseCase.getConversionRateByCurrency(currency)
            secondRate.value = rate?.toString()
        }
    }
}

2. 修改UI代码

点击确认按钮时触发数据获取,通过LaunchedEffect观察状态变化并打印结果:

if (viewModel.isDialogShown) {
    AlertDialog(
        onDismiss = {
            viewModel.onDismissClick()
        },
        onConfirm = {
            // 触发数据获取,而非同步拿返回值
            viewModel.fetchFirstConversionRate(viewModel.dropDownMenuItem1)
            viewModel.fetchSecondConversionRate(viewModel.dropDownMenuItem2)
        }
    )
}

// 监听汇率状态变化,当数据更新时打印
LaunchedEffect(viewModel.firstRate.value, viewModel.secondRate.value) {
    viewModel.firstRate.value?.let { println("First: $it") }
    viewModel.secondRate.value?.let { println("SECOND: $it") }
}
关键说明
  • 永远不要试图从异步函数中同步返回结果——协程的异步特性决定了数据不会立刻就绪。
  • 在Compose中,MutableState/StateFlow是连接ViewModel和UI的标准方式:ViewModel负责更新状态,UI通过收集状态变化自动刷新,完全符合MVVM的职责分离原则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 17:25:26