在一个协同程序中,我正在使用OkHttpClient执行一个http请求.请求是从一个包含suspend关键字的函数完成的:

suspend fun doSomethingFromHttp(someParam:String): Something {
    ...
    val response = HttpReader.get(url)
    return unmarshalSomething(response)!!
}

我假设函数可以在进入时挂起,因为它有关键字suspend,但是协程在执行http请求时也会挂起吗?其他类型的阻塞IO怎么办?

推荐答案

There's no automagic going on with Kotlin coroutines. If you call a blocking function like HttpReader.get(), the coroutine won't be suspended and instead the call will block. You can easily assure yourself that a given function won't cause the coroutine to suspend: if it's not a suspend function, it cannot possibly do it, whether or not it's called from a suspend function.

如果要将现有的阻塞API转换为非阻塞、可挂起的调用,必须将阻塞调用提交给线程池.实现这一目标的最简单方法如下:

val response = withContext(Dispatchers.IO) { HttpReader.get(url) }

withContext is a suspend fun that will suspend the coroutine, submit the provided block to another coroutine dispatcher (here IO) and resume when that block is done and has come up with its result.

您还可以轻松实例化自己的ExecutorService,并将其用作协同程序调度器:

val myPool = Executors.newCachedThreadPool().asCoroutineDispatcher()

现在你可以写作了

val response = withContext(myPool) { HttpReader.get(url) }

This way you work against a thread pool that is under your control, as opposed to the global IO. Just keep in mind that you are now also responsible to close() it.

Kotlin相关问答推荐

如果一项工作失败,请继续在Kotlin 等待其他工作/子元素完成

Android前台服务 list —Altbeacon

如何将时间值格式化为00:00和00:00:00 Kotlin?""""

在Kotlin 有更好的结合方式?

在Kotlin中的嵌套when语句中,else块是强制性的吗?

当我通过媒体通知更改音乐时不要更新我的 UI

如何在数据类中删除空格 (String)?

Kotlin supervisorScope 即使包裹在 try catch 中也会失败

kotest 更改环境变量

Picasso 回调

Swift vs Kotlin 在排序数组上的表现

API 'variant.getJavaCompile()' 已过时

调用单元测试验证伴随对象方法

Kotlin Compose,在行中对齐元素

如何在顶级函数中使用 koin 注入依赖项

如何处理 Kotlin 中的异常?

Kapt不适用于Android Studio 3.0中的AutoValue

如何解决:将Java类转换为Kotlin后出现error: cannot find symbol class ...?

Kotlin协程无法处理异常

如何使用mockk库模拟android上下文