我正在尝试在一个作业中使用 Room 执行两个数据库操作,但只有第一个操作正在执行。
在我的 ViewModel 中,我有以下内容:
val supervisorJob = SupervisorJob()
val scope = CoroutineScope(Dispatchers.Main + supervisorJob)
我有两个数据库操作返回Flow
,如下:
第一次操作:
firstRepo.getSomeData1().collect {
val size = it.size
Log.d(TAG, "Size of list is $size")
it.forEach {
Log.d(TAG, "Data1 name: ${it.name}")
}
}
第二个操作:
secondRepo.getSomeData2().collect {
val size = it.size
Log.d(TAG, "Size of list is $size")
it.forEach {
Log.d(TAG, "Data2 name: ${it.name}")
}
}
我正在尝试按照以下方式执行此操作,它只执行并打印 firstRepo.getSomeData1
并忽略 secondRepo.getSomeData2
我的方法:
fun getAllProtocols() = scope.launch {
withContext(Dispatchers.IO) {
firstRepo.getSomeData1().collect {
val size = it.size
Log.d(TAG, "Size of list is $size")
it.forEach {
Log.d(TAG, "Data1 name: ${it.name}")
}
}
secondRepo.getSomeData2().collect {
it.forEach {
Log.d(TAG, "Data2 name: ${it.name}")
}
}
}
}
如果我将每个操作包装在 launch{}
中,那么它们都会被执行。
我不明白为什么会这样?为什么他们不能在同一个工作中执行 还是强制一个作业只能执行一个异步或数据库操作?
最佳答案
同一个协程内的代码是顺序执行的。
流也是顺序的 - collect
函数只是一个常规的挂起函数,仅在收集整个流时(或抛出错误时)才返回。
换句话说,查看您的代码,这意味着第二个流的收集在第一个流完全收集之前无法开始。
问题是,第一个流永远不会被完全收集,因为它只是无限期地观察 Room 数据库的变化。
您已经知道如何解决这个问题 - 在单独的协程中启动收集操作以使其并发:
fun getAllProtocols() = scope.launch(Dispatchers.IO) {
launch {
firstRepo.getSomeData1().collect {
val size = it.size
Log.d(TAG, "Size of list is $size")
it.forEach {
Log.d(TAG, "Data1 name: ${it.name}")
}
}
}
launch {
secondRepo.getSomeData2().collect {
it.forEach {
Log.d(TAG, "Data2 name: ${it.name}")
}
}
}
}
关于android - 在单个作业中执行两个不同的操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59700503/