如何在委托类中正确处理协同程序



我需要关于如何正确地将协程上下文或范围传递给deledate类的建议。我有这个基础:

interface MyDelegate {
fun doWork()
}
class MyDelegateImpl() : MyDelegate {
override fun doWork() {
var job = async(Dispatcher.Default) {
// .....
}
.....
}
}
class MainViewModel(application: Application): AndroidViewModel(application), CoroutineScope, MyDelegate by MyDelegateImpl() {
.....
}
class MainActivity : AppCompatActivity() {
.....
private lateinit var mainViewModel: MainViewModel

.....

private fun initialize() {
.....
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
}

fun doAction() {
mainViewModel.doWork()
}
}

构建时,它在doWork((中抛出一个异步错误:

未解析的引用。由于接收器类型不匹配,以下候选者均不适用:public fun CoroutineScope.async(context:CoroutineContext=…,start:Coroutine start=…,block:shupend-CoroutineScope.((->TypeVariable(T((:递延<类型变量(T(>在kotlinx.coroutines中定义

我尝试用CouroutineScope接口扩展MyDelegateImpl:

class MyDelegateImpl(override val coroutineContext: CoroutineContext) : MyDelegate, CoroutineScope {
.....
}

但我不知道该如何在MainViewModel中传递它,当然在接口列表中是不可能的。

首先,我在工人类的构造函数中给它一个CoroutineScope属性,让它使用:

class MyDelegateImpl(val scope: CoroutineScope) : MyDelegate {
override fun doWork() {
var job = scope.async(Dispatcher.Default) {
// .....
}
.....
}
}

下一部分有点尴尬。您通常希望使用提供的viewModelScope,因为它已经可用,并且设置为适当地取消它自己。但它是惰性创建的,因此在类构造期间不可用,因此您可以将它传递给委托。

我认为在这种情况下,我会隐藏viewModelScope扩展属性,这样就不会创建多余的作用域。你需要在onCleared()中清理它。

它需要在主构造函数中,这样才能传递给委托,但你想封装它的创建,所以我会将主构造函数设为私有构造函数,并在公共的辅助构造函数中创建它。

class MainViewModel private constructor(
val viewModelScope: CoroutineScope,
application: Application
): AndroidViewModel(application), MyDelegate by MyDelegateImpl(viewModelScope) {

constructor(application: Application): this(
CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate),
application
)
override fun onCleared() {
viewModelScope.cancel()
}
}

最新更新