19

What is the difference between Dispatchers.Main and Dispatchers.Default in Kotlin coroutines?

I used viewModelScope.launch {} and launch block as expected is executed on UI thread. Then I discovered that it defaults to viewModelScope.launch(Dispatchers.Default) {}.

This was a bit confusing to me as I thought that I should use Dispatchers.Main to perform operations on the UI thread.

So far it looks like that on Android Dispatchers.Default is defaulting to Dispatchers.Main. Is that right?

Is there any drawbacks if I use one or another or they are interchangeable? If they are interchangeable on Android, is it going to affect something if in future I will add support of kotlin multiplatform?

Johann
  • 27,536
  • 39
  • 165
  • 279
Vadims Savjolovs
  • 2,618
  • 1
  • 26
  • 51
  • 4
    The default is actually `Dispatchers.Main`. See [here](https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/lifecycle/lifecycle-viewmodel-ktx/src/main/java/androidx/lifecycle/ViewModel.kt#42). [This blog post](https://proandroiddev.com/usage-of-the-viewmodelscope-f28703467b31) says the same too. – Marko Topolnik Jan 08 '20 at 13:43
  • Ohh I see my mistake now, I was looking into wrong doc – Vadims Savjolovs Jan 08 '20 at 13:59
  • On Android, Main and Default are the same. But if you were using Coroutines on a different platform that doesn't support UIs and was entirely hardware-oriented, you could theoretically have Default use IO instead of Main. – Johann Nov 23 '22 at 08:53

1 Answers1

19

Then I discovered that it defaults to viewModelScope.launch(Dispatchers.Default) {}.

No, viewModelScope.launch() defaults to Dispatchers.Main.immediate. Google overrides the ordinary default launch() dispatcher, which is Dispatchers.Default. I recommend always specifying the dispatcher, rather than having to make people guess which one gets used in which circumstances.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 1
    My recommendation is this: everything should always launch in `Main`, this should be the understood assumption in the whole project. If some specific piece of code works with blocking IO, it should use `withContext(IO)` on the inside, as an implementation detail. Messing with dispatchers is not something that belongs to top-level abstractions. – Marko Topolnik Jan 08 '20 at 14:30
  • 1
    @MarkoTopolnik As long as its a shared assumption... But it is not at all clear. And the override of Default to Main is not something everyone is aware of, so I would agree with the statement "always specifying the dispatcher, rather than having to make people guess which one gets used in which circumstance" – Dmitri Jan 08 '20 at 17:08
  • 1
    @Dmitri The default of `Main` is actually the most natural default on Android, I don't see any room for confusion, especially if you employ the discipline of not launching in any other dispatcher. It means the coroutine will run on the same thread you launch it from and the entire concern of special-purpose dispatchers will be confined to the logic that requires them. – Marko Topolnik Jan 08 '20 at 17:20
  • 1
    @MarkoTopolnik My point is that if you start by looking at the defaults assumed by Dispatchers in general, it is natural to assume those same defaults would be used elsewhere. The person who posted this question assumed so, and so did I until recently when I discovered the different default by looking at the source code. And the official documentation doesn't mention it either - https://developer.android.com/topic/libraries/architecture/coroutines – Dmitri Jan 08 '20 at 17:28
  • 1
    @Dmitri But that default applies only when you use an Android-specific CoroutineScope, such as `MainScope` or `viewModelScope`. Android doesn't actually override or change any global defaults, it just defines some standard scopes. I agree, however, that the docs on `viewModelScope` should be more explicit about it, even though I personally had no doubt which dispatcher it uses. – Marko Topolnik Jan 08 '20 at 18:40
  • To add to the confusion, couple of the examples in the coroutines best practices guide show injecting Dispatchers.Default when creating coroutines in the business and data layer. [coroutines-best-practices](https://developer.android.com/kotlin/coroutines/coroutines-best-practices#create-coroutines-data-layer) – Pitos Dec 01 '22 at 13:17
  • 1
    This answer is wrong. viewModelScope uses `Dispatchers.Main.immediate` – Daniele Segato Mar 16 '23 at 19:28