如何在Kotlin中创建异步发布请求



我正在尝试向服务器发送POST请求并获取一些数据。我尝试在主线程上运行请求,但它一直给我一个错误,所以我决定使用coroutines将其作为异步线程运行。这就是我目前所拥有的:

class requests{
private val client = OkHttpClient()

fun run() = runBlocking {
launch {
val postBody = """
|Releases
|--------
|
| * _1.0_ May 6, 2013
| * _1.1_ June 15, 2013
| * _1.2_ August 11, 2013
|""".trimMargin()
val request = Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(postBody.toRequestBody(MEDIA_TYPE_MARKDOWN))
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
println(response.body!!.string())
}
}
}
companion object {
val MEDIA_TYPE_MARKDOWN = "text/x-markdown; charset=utf-8".toMediaType()
}

}

当我运行requests().run()时,我得到以下错误:

android.os.NetworkOnMainThreadException

我不知道为什么会出现这个错误,我认为coroutines创建了一个新线程来防止这种情况发生。

runBlocking不切换线程,因此如果在主线程上调用它,协程将在主线程中启动。这个方法阻塞当前线程,所以永远不要在生产中使用它:阻塞线程的性能非常低,你应该创建一个新的协同程序,并在那里启动你的代码

Coroutine本身可以在主线程上毫无问题地工作,但您正在运行的代码可以检查当前线程,在这种情况下会发生什么——它抛出一个异常

以下代码应该适用于您:

class requests{
private val client = OkHttpClient()
private val coroutineScope = CoroutineScope(Dispatchers.Default)
fun run()  {
coroutineScope.launch {
val postBody = """
|Releases
|--------
|
| * _1.0_ May 6, 2013
| * _1.1_ June 15, 2013
| * _1.2_ August 11, 2013
|""".trimMargin()
val request = Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(postBody.toRequestBody(MEDIA_TYPE_MARKDOWN))
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
println(response.body!!.string())
}
}
}
companion object {
val MEDIA_TYPE_MARKDOWN = "text/x-markdown; charset=utf-8".toMediaType()
}

}

另一种方法是使run成为suspend函数,并从外部协同程序运行它——如果您想从调用返回结果,则首选此方法

最新更新