How can CoroutineScope(job+Dispatchers.Main) run on the main/UI thread?

372 :

If the operations inside CoroutineScope(job+Dispatchers.Main){...} run on the main thread then how come it does not violate Android's requirement that slow (blocking) operations (Networking etc.) are not allowed to run on the main/UI thread? I can run blocking operations with this scope and the UI does not freeze at all.

I would be grateful if someone could explain what is happening under the hood. My guess is that it is similar to how JavaScript manages blocking operations with the event loop, but I struggle to find any relevant materials.

Marko Topolnik :

My guess is that it is similar to how JavaScript manages blocking operations with the event loop

Yes, this is correct, the event loop is essential to making coroutines work. Basically, when you write this:

uiScope.launch {
    delay(1000)
    println("A second has passed")
}

it compiles into code that has the same effect as this:

Handler(Looper.mainLooper()).postDelayed(1000) { println("A second has passed") }

The main concept is the continuation, an object that implements a state machine that corresponds to the sequential code you wrote in a suspendable function. When you call delay or any other suspendable function, the continuation's entry-point method returns a special COROUTINE_SUSPENDED value. Later on, when some outside code comes up with the return value of the suspendable function, it must call continuation.resume(result). This call will be intercepted by the dispatcher in charge, which will post this call as an event on the GUI event loop. When the event handler is dequeued and executed, you are back inside the state machine which figures out where to resume the execution.

You can review this answer for a more fleshed-out example of using the Continuation API.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=7244&siteId=1
Recommended