user3087615
user3087615

Reputation: 385

When and how to call suspend function from Android Activity?

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

Answers (2)

Nurseyit Tursunkulov
Nurseyit Tursunkulov

Reputation: 9390

If you want to write in activity:

class MyActivity : AppCompatActivity() {
private val scope = CoroutineScope(newSingleThreadContext("name"))

fun doSomething() {
    scope.launch { ... }
  }
}

Upvotes: 3

Bartek Lipinski
Bartek Lipinski

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):

  1. Read 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

Related Questions