LiuWenbin_NO.
LiuWenbin_NO.

Reputation: 1326

What's the relationship between this Kotlin CoroutineScope and Dispatcher and CoroutineContext

enter image description here

As attached, the code (from Kodeco at here) is in an Android Fragment, I was wondering what's the relationship of Dispatchers.Main between these two lines:

L63: private val coroutineScope = CoroutineScope(Dispatchers.Main + parentJob)
L68: coroutineScope.launch(Dispatchers.Main) { .. }

What by my understanding is, the Dispatchers.Main on L63 means the coroutineScope is bound to Main thread, and the Dispatchers.Main on L68 means the coroutine block will be run in Main thread.

But do I have to specify it twice? What if I don't do like this, for example, what happens if I change L68 to be like: coroutineScope.launch {..}

Upvotes: 2

Views: 1022

Answers (1)

LiuWenbin_NO.
LiuWenbin_NO.

Reputation: 1326

Sorry for this dumb question, I got it now like below:

L63: private val coroutineScope = CoroutineScope(Dispatchers.Main + parentJob)

This specifies a custom coroutine scope, and this scope has been bound to the Dispatchers.Main (the main thread, and let's ignore parentJob in this question).

has bound to Dispatchers.Main means: the coroutine started by this scope will run in main thread.

And on L68:

L68: coroutineScope.launch(Dispatchers.Main) { .. }

this specifies, again, the coroutine block will run in main thread. So as for the again here, I mean, by looking into the source code of launch function, I found this:

val newContext = newCoroutineContext(context)

And there is a context combination in the function of newCoroutineContext(context) which looks like:

val combined = coroutineContext + context

which means add the L68's Dispatchers.Main onto the L63's Dispatchers.Main, owing to they are the same, so finally the coroutine block after L68 will run in the main thread.

So to answer my question: what happens if I change L68 to be like: coroutineScope.launch {..}, nothing will change, everything is exactly the same, since before and after, the coroutine block will run on main thread consistently.

But, what if we change the L68 like:

coroutineScope.launch(Dispatchers.IO) { .. }

Well, this time, the app will crash because of it's trying to update the UI from a worker thread:

E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-4
    Process: com.raywenderlich.snowy, PID: 8562
    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

This is because, the L68's Dispatchers.IO overrode the L63's Main.

Just keep the question and my post for a while here, in case it could help someone like me had the same confuse.

Upvotes: 2

Related Questions