多ViewModel共享类中应使用何种Kotlin协程作用域?
共享类中协程作用域的正确处理方式
为什么GlobalScope不合适
GlobalScope的生命周期和整个应用绑定,不会随着ViewModel的销毁而自动取消协程,这会引发两个关键问题:一是容易造成内存泄漏,二是ViewModel销毁后,后台协程仍可能执行无效操作(比如更新已不存在的UI),完全违背了你希望由ViewModel主导作用域的初衷。
正确思路:让调用方(ViewModel)控制作用域
这个共享类本质是工具类或业务逻辑类,它不应该拥有独立的协程作用域,而是由调用它的ViewModel提供作用域,让协程生命周期与ViewModel绑定,ViewModel销毁时协程自动取消。
有两种常见实现方式:
1. 直接在ViewModel作用域内调用挂起方法
如果共享类的方法仅为挂起函数(无需主动启动协程),直接在ViewModel的viewModelScope中调用即可:
// 共享类 class SharedBusinessClass { // 挂起方法,内部仅处理耗时逻辑,不启动协程 suspend fun performSuspendOperation(): Result { delay(1000) // 模拟挂起操作 return Result.success() } } // ViewModel中使用 class MyViewModel(private val sharedClass: SharedBusinessClass) : ViewModel() { fun triggerOperation() { viewModelScope.launch { val result = sharedClass.performSuspendOperation() // 处理结果,比如更新UI状态 } } }
2. 让共享类接收外部传入的作用域
如果共享类需要内部启动协程,就在方法参数中接收CoroutineScope,由ViewModel传入自己的viewModelScope:
// 共享类 class SharedBusinessClass { fun startAsyncTask(scope: CoroutineScope, onResult: (Result) -> Unit) { scope.launch { val result = performSuspendOperation() onResult(result) } } private suspend fun performSuspendOperation(): Result { delay(1000) return Result.success() } } // ViewModel中使用 class MyViewModel(private val sharedClass: SharedBusinessClass) : ViewModel() { fun triggerTask() { sharedClass.startAsyncTask(viewModelScope) { result -> // 处理结果 } } }
为什么ViewModel用viewModelScope
viewModelScope是Jetpack为ViewModel量身设计的作用域,它会在ViewModel调用onCleared()时自动取消所有子协程,完美适配ViewModel的生命周期。而共享类作为被多个ViewModel共享的依赖,本身没有独立生命周期,它的协程必须由调用它的ViewModel掌控,才能保证每个ViewModel的协程在自身销毁时被正确清理。
内容的提问来源于stack exchange,提问作者StackOverflower
相关产品推荐
相关产品推荐

