单屏幕调用多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
相关产品推荐
相关产品推荐

