【发布时间】:2018-12-19 02:21:49
【问题描述】:
我从 Android 应用中的协程开始。我正在重写对suspendCoroutine<> {} 的回调,但我遇到了一个难题:什么时候应该将函数标记为suspend,什么时候应该将调用包含在某个构建器中(launch、async 等? )?
是否有一些最佳实践、经验法则之类的?
【问题讨论】:
标签: kotlin coroutine kotlin-coroutines
我从 Android 应用中的协程开始。我正在重写对suspendCoroutine<> {} 的回调,但我遇到了一个难题:什么时候应该将函数标记为suspend,什么时候应该将调用包含在某个构建器中(launch、async 等? )?
是否有一些最佳实践、经验法则之类的?
【问题讨论】:
标签: kotlin coroutine kotlin-coroutines
您应该为当前正在进行的每个异步、基于回调的 API 调用编写一个 suspend fun。
您应该在 withContext(myThreadPool) 中包含您正在进行的每个同步 API 调用。
所有执行 I/O 的 Android 友好 API 都使用异步方法,因此对于这些,您将编写 suspend funs,但对于 CPU 密集型任务(例如解码图像),您可能需要 withContext。
最后,为了能够使用任何一种调用,您必须使用launch(UI) 创建一个顶级协程。
请记住,以上内容实际上只是一个经验法则。当您分解代码时,很多时候您会意识到您需要 suspend fun 来执行 CPU 密集型操作,因为在该调用路径的某处有一个 withContext。
让我还添加一个关于非常典型的协同程序 API 滥用的警告:你几乎不需要async-await。仅在您希望在“后台”真正运行它同时继续在当前上下文中执行其他操作的情况下使用它。简单来说,你永远不应该写
val result = async { calculation() }.await()
你应该写
val result = withContext(myThreadPool) { calculation() }
【讨论】:
suspending(带有suspendCoroutine的函数),可以将所有调用该函数的函数也标记为suspend?跨度>