我已经阅读了数十篇帖子,但不知何故,似乎没有一个答案对我有用。
我想要实现的是在Fragment中等待ViewModel使用Room进行操作。
道:
@Query("SELECT * FROM my_table WHERE id = :id")
suspend fun getMyData(id: Long): List<Item>
在 ViewModel 中,我不需要返回任何内容,只需使用数据库中的一些数据更新我的变量即可。我也在这里尝试了其他方法,即返回一个 Deferred
视图模型:
suspend fun updateData(myItem: Item) {
for (myField in myItem.fields) {
myField.someOtherField = myDao.getMyData(myField.id)
}
}
我尝试过使用 runBlocking、lifecycleScope.launch 和 async.await() 等待,但总是得到相同的结果。我需要处理更新的项目。
片段:
runBlocking {
val job = launch{
viewModel.updateData(myItem)
}
job.join()
doSomethingElseWithUpdatedmyItem(myItem) //this always executes before viewModel.updateData(myItem) even starts
}
答案 0 :(得分:0)
如果不涉及其他代码,则应按此顺序运行。
runBlocking {
println("run blocking")
val job = launch {
delay(1000)
println("launch new job")
}
job.join()
println("do something")
}
此代码将打印:
run blocking
launch new job
do something
在您的情况下,我会使用 withContext/async
作为 viewModel.updateData
逻辑。
答案 1 :(得分:0)
是否有理由不只是在协程中运行最终代码?
lifecycleScope.launch {
viewModel.updateData(myItem)
doSomethingElseWithUpdatedmyItem(myItem)
}
这就是使用协程的真正用途。
不过,最终,我想知道这里的问题是否与您的项目的可变性有关。为什么不返回一组新的项目而不是尝试改变现有的项目?然后你会有类似的东西
suspend fun updateData(myItem: Item): Item {
return myItem.copy(
fields = myItem.fields.map { field -> myDao.getMyData(field.id) }
)
}
然后您将更新后的项目传递给您的最终函数:
lifecycleScope.launch {
val updatedItem = viewModel.updateData(myItem)
doSomethingElseWithUpdatedmyItem(updatedItem)
}