Reputation: 385
I have a suspend
function that calls POST request to the server. I want to configure some text in the activity to show the information I received from the server.
suspend fun retrieveInfo():String
I tried calling inside onCreate
, onResume
but crashes runtime.
runBlocking {
retrieveInfo()
}
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.google.augmentedimage/com.google.AugmentedImageActivity}: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3086)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3229)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
Where am I suppose to put these suspend calls (in which part of lifecycle of activity)? Should I be using something other than runBlocking
?
Upvotes: 17
Views: 28179
Reputation: 9390
If you want to write in activity:
class MyActivity : AppCompatActivity() {
private val scope = CoroutineScope(newSingleThreadContext("name"))
fun doSomething() {
scope.launch { ... }
}
}
Upvotes: 3
Reputation: 31448
By default runBlocking
runs the suspending code block
in the thread runBlocking
was called on.
So if you called runBlocking
from the Activity
callback your suspending block will be executed on the main thread, from which you cannot access network (query a server).
You need to switch a dispatcher in your coroutine block for that call. The simplest fix for your code would be to move the execution to the Dispatchers.IO
.
runBlocking {
withContext(Dispatchers.IO) {
retrieveInfo()
}
}
That being said, I suggest two things (not related directly to your question):
Coroutines on Android
(this part and the following ones)2. Don't use runBlocking
for your case, but define a correct job
and use job.launch{}
Upvotes: 16