冗余的'async'调用可以减少到'kotlinx.coroutines.withContext'有什么好处?

wswtfjt7  于 2023-03-13  发布在  Kotlin
关注(0)|答案(1)|浏览(154)

我有下面的代码:

suspend fun add(article: Article): Long {
  return CoroutineScope(IO).async {
    articleDao.add(article)
  }.await()
}

我想等待结果,所以使用async。但Android Studio提示我优化代码,如下所示:

suspend fun add(article: Article): Long {
    return withContext(CoroutineScope(IO).coroutineContext) {
      articleDao.add(article)
    }
  }

我刚开始学习Kotlin协程,我知道withContext是用来切换线程的。
但是在这个例子中,withContext似乎也保证等待返回值,你能告诉我更多关于这个的信息吗?

flvlnr44

flvlnr441#

在您的原始代码片段中存在2个问题:

suspend fun add(article: Article): Long {
  return CoroutineScope(IO).async {
    articleDao.add(article)
  }.await()
}

你不应该在函数中本地创建这样的CoroutineScope,这违反了结构化并发的约定。
或者换句话说,由async创建的Deferred<A>易于泄漏,因为它没有耦合到外部suspend作用域或任何父生命周期。
这可以通过使用coroutineScope Scope生成器来修复。

suspend fun add(article: Article): Long {
  return coroutineScope {
    async {
      articleDao.add(article)
    }.await()
  }
}

第二个问题,也就是您在问题中提出的问题,是“withContext的好处”。
withContext的好处是它比async优化得多,它可以检测协程是否已经在所需的Dispatcher内,然后可以避免调度。它也有一个更优化的运行时,不需要CoroutineScope,因此不需要coroutineScope构建器。

suspend fun add(article: Article): Long {
  return withContext(IO) {
    articleDao.add(article)
  }
}

总而言之,withContext允许你高效地在所需的DispatcherCoroutineContext上运行suspend fun,避免不必要的调度。而async创建一个Deferred,类似于Java Future,它在new协程中运行suspend fun

相关问题