如何让挂起函数执行完成后再调用非挂起函数,避免使用Deferred?
可行方案分析与推荐
针对你的场景,有几种合理的实现方式,下面逐一说明:
1. 你考虑的Lambda回调方案(可行但非最优)
这种方式直接简单,符合常规回调思维,实现起来没有问题。
ViewModel实现:
fun clearFirebaseCache(onComplete: () -> Unit) { viewModelScope.launch { // 执行挂起的缓存清理逻辑 clearFirebaseCacheUseCase.execute() // 清理完成后触发回调 onComplete() } }
MainActivity调用:
viewModel.changeLanguageConsumableLiveData.observe(this) { viewModel.clearFirebaseCache { ProcessPhoenix.triggerRebirth(this) } }
优缺点:
- 优点:代码直观,快速上手,不需要额外的LiveData或协程语法。
- 缺点:ViewModel与回调逻辑耦合,单元测试时需要模拟回调;如果后续需要添加错误处理,还要额外增加错误回调参数,扩展性一般。
2. 推荐:将clearFirebaseCache改为挂起函数
利用协程的挂起特性,让Activity在自己的生命周期协程里顺序执行逻辑,这是最符合Jetpack协程最佳实践的方式。
ViewModel实现:
suspend fun clearFirebaseCache() { clearFirebaseCacheUseCase.execute() }
MainActivity调用:
viewModel.changeLanguageConsumableLiveData.observe(this) { lifecycleScope.launch { // 等待缓存清理完成 viewModel.clearFirebaseCache() // 执行重启操作 ProcessPhoenix.triggerRebirth(this@MainActivity) } }
优缺点:
- 优点:代码简洁连贯,完全遵循结构化并发;
lifecycleScope会自动绑定Activity生命周期,避免内存泄漏;ViewModel职责单一,只负责业务逻辑,不关心后续操作。 - 缺点:需要了解协程挂起的基本概念,但对于已经使用协程的项目来说,这是标准用法。
3. LiveData事件通知方案(解耦性好)
如果想严格遵循单向数据流设计,可通过LiveData发送缓存清理完成的事件,Activity观察该事件执行重启。
ViewModel实现:
// 假设你已经有Consumable包装类避免重复触发 private val _cacheClearedEvent = MutableLiveData<Consumable<Unit>>() val cacheClearedEvent: LiveData<Consumable<Unit>> = _cacheClearedEvent fun clearFirebaseCache() { viewModelScope.launch { clearFirebaseCacheUseCase.execute() _cacheClearedEvent.value = Consumable(Unit) } }
MainActivity调用:
// 监听语言变更事件,触发缓存清理 viewModel.changeLanguageConsumableLiveData.observe(this) { viewModel.clearFirebaseCache() } // 监听缓存清理完成事件,执行重启 viewModel.cacheClearedEvent.observe(this) { event -> event.consume { ProcessPhoenix.triggerRebirth(this) } }
优缺点:
- 优点:完全解耦,ViewModel只负责发送事件,Activity负责响应,符合MVVM的单向数据流理念;便于扩展(比如后续可添加错误事件)。
- 缺点:需要多定义一个LiveData,代码量稍多;事件传递的链路更长,调试时需要多一步跟踪。
总结
优先推荐挂起函数方案,它既简洁又符合协程的设计原则;如果项目严格遵循单向数据流,可选择LiveData事件方案;Lambda回调方案可以用,但长期来看不利于代码维护和扩展。
内容的提问来源于stack exchange,提问作者ant2009
相关产品推荐
相关产品推荐

