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

单屏幕调用多ViewModel函数vs单ViewModel函数:哪种方案更优?

问题场景与两种实现方案

假设在OrderScreen中,我们需要使用OrderViewModel(orderRepository)和UserViewModel(userRepository),以下是两种实现方案:

方案一

class OrderViewModel(private val orderRepository: OrderRepository) : ViewModel() {
    fun doSomething() = viewModelScope.launch {
        orderRepository.doSomething()
    }
}

class UserViewModel(private val userRepository: UserRepository): ViewModel() {
    fun doSomething() = viewModelScope.launch {
        userRepository.doSomething()
    }
}

@Composable
fun OrderScreen(
    orderViewModel: OrderViewModel = viewModel(),
    userViewModel: UserViewModel = viewModel()
) {
    someButton.setOnclickListener {
        orderViewModel.doSomething()    //<<- 是否存在多线程问题?
        userViewModel.doSomething()
    }
}

方案二

class OrderViewModel(
    private val orderRepository: OrderRepository,
    private val userRepository: UserRepository
) : ViewModel() {
    fun doSomething() = viewModelScope.launch {
        orderRepository.doSomething()    
        userRepository.doSomething()
    }
}

@Composable
fun OrderScreen(orderViewModel: OrderViewModel = viewModel()) {
    someButton.setOnclickListener {
        orderViewModel.doSomething()
    }
}

请问哪种方案更优?原因是什么?


方案二更优,原因如下:
  • 逻辑内聚性更强:按钮点击触发的是一个完整的业务动作,方案二把关联的订单、用户操作封装在同一个OrderViewModel的方法里,后续修改该业务逻辑时只需改动一处代码,可读性与维护性更佳。
  • 执行顺序可控:方案一中两个ViewModel的方法会启动独立协程并行执行,业务操作的先后顺序不可控;方案二则在同一个协程内顺序执行两个Repository的方法,能保证订单操作完成后再执行用户操作,满足多数业务场景的顺序要求。
  • 简化依赖与实例:方案一需要在OrderScreen中初始化两个ViewModel,方案二仅需一个,既减少了内存中的实例数量,也简化了Composable函数的参数结构。
  • 关于方案一的多线程疑问:方案一中的协程都基于viewModelScope(默认调度器为Dispatchers.Main.immediate),本身不会有线程安全问题,但并行执行的两个操作可能导致业务状态更新顺序混乱,引发UI显示不一致的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 14:15:02