Reputation: 440
I'm trying to send a POST request to a server and get some data. I tried running the request on the main thread but it kept giving me an error so I decided to use coroutines
to run it as an async thread. This is what I have so far:
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()
}
}
When I run requests().run()
I get the following error:
android.os.NetworkOnMainThreadException
I'm not sure why I'm getting this error, I thought that coroutines
creates a new thread to prevent this from happening.
Upvotes: 2
Views: 2351
Reputation: 88022
runBlocking
doesn't switch a thread, so if you call it on a main thread, coroutine will be too launched on a main thread. This method blocks current thread so never use it it the production: blocking a thread is very low performant, you should create a new coroutine instead and launch your code there
Coroutine by itself can work on main thread without problems, but the code you're running can check current thread, and what happens in this case - it throws an exception
The following code should work for you:
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()
}
}
An other approach is making run
a suspend
function and running it from an outside coroutine - it'll be preferred in case you'd like to return a result from your calls
Upvotes: 2