繁体   English   中英

如何等待 Kotlin 协程完成

[英]How to wait for a Kotlin coroutine to finish

我已经阅读了数十篇文章,但不知何故,在我的情况下似乎没有一个答案有效。

我想要实现的是在 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
}                            

如果没有涉及其他代码,那么它应该按此顺序运行。

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逻辑。

您是否有理由不只是在协程中运行最终代码?

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) }
    )
}

然后您将更新的项目传递给您的最终 function:

lifecycleScope.launch {
    val updatedItem = viewModel.updateData(myItem)
    doSomethingElseWithUpdatedmyItem(updatedItem)
}   

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM