[英]How to wait for a Kotlin coroutine to finish
I've read dozens of posts, but somehow none of the answers seems to work in my case.我已经阅读了数十篇文章,但不知何故,在我的情况下似乎没有一个答案有效。
What I want to achieve is is to wait in Fragment for ViewModel to perform operations using Room.我想要实现的是在 Fragment 中等待 ViewModel 使用 Room 执行操作。
Dao:道:
@Query("SELECT * FROM my_table WHERE id = :id")
suspend fun getMyData(id: Long): List<Item>
In the ViewModel I don't need to return anything, just update my variable with some data from the database.在 ViewModel 中,我不需要返回任何内容,只需使用数据库中的一些数据更新我的变量。 I've tried other approaches here as well, ie returning a Deferred
我在这里也尝试过其他方法,即返回 Deferred
ViewModel:视图模型:
suspend fun updateData(myItem: Item) {
for (myField in myItem.fields) {
myField.someOtherField = myDao.getMyData(myField.id)
}
}
I've tried waiting with runBlocking, lifecycleScope.launch, with async.await() but always with the same result.我尝试过使用 runBlocking、lifecycleScope.launch 和 async.await() 等待,但结果总是相同。 I need to work on an updated item.
我需要处理更新的项目。
Fragment:分段:
runBlocking {
val job = launch{
viewModel.updateData(myItem)
}
job.join()
doSomethingElseWithUpdatedmyItem(myItem) //this always executes before viewModel.updateData(myItem) even starts
}
If there is no other code involved then it should run in this order.如果没有涉及其他代码,那么它应该按此顺序运行。
runBlocking {
println("run blocking")
val job = launch {
delay(1000)
println("launch new job")
}
job.join()
println("do something")
}
This code will print:此代码将打印:
run blocking
launch new job
do something
In your case, I would use withContext/async
for the viewModel.updateData
logic.在您的情况下,我将
withContext/async
用于viewModel.updateData
逻辑。
Is there a reason you are not just running the final code inside the coroutine ?您是否有理由不只是在协程中运行最终代码?
lifecycleScope.launch {
viewModel.updateData(myItem)
doSomethingElseWithUpdatedmyItem(myItem)
}
That's using coroutines how they are really meant to be used.那就是使用协程,它们的真正用途是什么。
Ultimately, though, I wonder if this problem here is in the mutability of your items.不过,最终,我想知道这里的问题是否在于您的项目的可变性。 Why not return a new set of items instead of trying to mutate the existing ones?
为什么不返回一组新项目而不是尝试改变现有项目? Then you'd have something like
然后你会有类似的东西
suspend fun updateData(myItem: Item): Item {
return myItem.copy(
fields = myItem.fields.map { field -> myDao.getMyData(field.id) }
)
}
And then you'd pass the updated item to your final function:然后您将更新的项目传递给您的最终 function:
lifecycleScope.launch {
val updatedItem = viewModel.updateData(myItem)
doSomethingElseWithUpdatedmyItem(updatedItem)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.