为什么使用withContext() vs Async-await,不是协程实现并发的目标吗?

ext*_*ats 1 concurrency android async-await kotlin

我正在学习线程和 kotlin 协程以同时加载我的 UI 和存储库,但随后将“withContext()”作为异步等待的替代方法。如果我正确理解“withContext()”并且它执行一个又一个任务等待前一个任务完成,为什么还要使用它?我还缺少另一个概念吗?

Jof*_*rey 6

withContext是一个挂起函数,允许在不同的协程上下文中执行一段特定的代码。当您想在不同的调度程序中执行某些操作时,它特别有用。

例如,您可以在具有多个线程的默认调度程序中运行一些代码,然后使用该代码生成的值来更新 UI 线程中的某些 UI。在这种情况下,您不是在寻找并发性,默认调度程序上的计算必须在更新 UI 之前发生,因为您需要结果:

val result = someComputation()
withContext(Dispatchers.Main) {
    updateUI(result)
}
Run Code Online (Sandbox Code Playgroud)

当然,即使 UI 的计算和更新不是并发的,它们的顺序也可以与其他代码段并发:

scope.launch(Dispatchers.Default) {
    val result = someComputation()
    withContext(Dispatchers.Main) {
        updateUI(result)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你需要执行并发的事情,你可以使用像launch和这样的协程构建器async。然而,使用async { ... }紧跟其后.await()违背了并发的目的,因为asyncawait()调用之间的代码正是将与async的主体并发运行的代码:

val deferred = async { computeSomeValue() }
somethingConcurrentWithAsyncBody()
val result = deferred.await()
Run Code Online (Sandbox Code Playgroud)

您可以在有关组合挂起函数的文档部分阅读更多有关如何组织调用以实现并发的信息。

  • @extremeoats 当您调用“async{}”时,将启动一个新的协程并与当前协程同时运行。`async` 主体中的代码与 `async{}` 后面的代码“同时”执行。调用“await()”会挂起当前协程,以便等待接收者“Deferred”完成 - 这意味着它等待异步主体完成执行。因此,如果您调用 async 来启动并发计算,但随后您立即停止并等待它,而不是在它工作时执行某些操作,那么您就没有利用并发性。是不是更清楚了? (2认同)