What is the Purpose of the Main Dispatcher?
Tags: kotlin, coroutine, dispatchers, dispatchersmain
Published: 2024-03-21 06:15:13

---
title: What is the Purpose of the Main Dispatcher?
published: true
series: My Kotlin World
description: 
tags: kotlin,coroutine,dispatchers,DispatchersMain
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ok33j07y9yj3x2mlz9g5.png
# Use a ratio of 100:42 for best results.
# published_at: 2024-03-21 06:09 +0000
---

If you have this question, perhaps you are a long time server-side developer and are wondering what the Main Dispatcher is doing in the Kotlinx coroutines library? Well, the Main Dispatcher exists as kind of an interface, but its implementation isn't really there.

The Main dispatcher is used in Kotlin when programming something that will interact with some sort of UI. For the Dispatchers.Main scope to be available, one of these needs to be available: Android main thread dispatcher, JavaFx, or Swing EDT dispatcher. The Main dispatcher has one distinct characteristic that tells it apart from the others. This dispatcher is singe-threaded and it is not shipped with the kotlinx coroutines library.

Let’s look at one example:

```kotlin
class MainDispatcherLauncher {

    companion object {
        val logger: Logger = LoggerFactory.getLogger(MainDispatcherLauncher::class.java)

        @JvmStatic
        fun main(args: Array<String> = emptyArray()) = runBlocking {
            runMainCoroutinesTest()
        }

        private suspend fun runMainCoroutinesTest() {
            try {
                val job = CoroutineScope(Dispatchers.Main).launch {
                    launch {
                        delay(100)
                        logger.info("This is cat @ ${LocalDateTime.now()}")
                    }
                    launch {
                        logger.info("This is mouse @ ${LocalDateTime.now()}")
                    }
                    logger.info("This is master @ ${LocalDateTime.now()}")
                }
                job.join()
            } catch (ex: IllegalStateException) {
                logger.info("Error!", ex)
            }
        }

    }
}
```

In this case, both launches would kickstart two coroutines and we would expect at least 3 log outputs in a normal situation. However, this will not work if simply running a standalone application or in a server-side setting. Since the Main disptacher isn’t available, running this code will result in:

```java
Exception in thread "main" java.lang.IllegalStateException: Module with the Main dispatcher is missing. Add dependency providing the Main dispatcher, e.g. 'kotlinx-coroutines-android' and ensure it has the same version as 'kotlinx-coroutines-core'
	at kotlinx.coroutines.internal.MainDispatchersKt.throwMissingMainDispatcherException(MainDispatchers.kt:77)
	at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.missing(MainDispatchers.kt:108)
	at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.isDispatchNeeded(MainDispatchers.kt:92)
	at kotlinx.coroutines.test.internal.TestMainDispatcher.isDispatchNeeded(TestMainDispatcher.kt:31)
	at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:315)
	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:26)
	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:21)
	at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:88)
	at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:123)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:52)
	at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:43)
	at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
	at org.jesperancinha.ktd.MainScopeLauncher$Companion.runMainCoroutinesTest(MainScopeLauncher.kt:20)
	at org.jesperancinha.ktd.MainScopeLauncher$Companion.access$runMainCoroutinesTest(MainScopeLauncher.kt:10)
	at org.jesperancinha.ktd.MainScopeLauncher$Companion$main$1.invokeSuspend(MainScopeLauncher.kt:15)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:277)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:95)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:69)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:48)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at org.jesperancinha.ktd.MainScopeLauncher$Companion.main(MainScopeLauncher.kt:14)
	at org.jesperancinha.ktd.MainScopeLauncher.main(MainScopeLauncher.kt)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@2c039ac6, Dispatchers.Main]
06:44:49.864 [main] INFO org.jesperancinha.ktd.MainScopeLauncher -- Error!
java.lang.IllegalStateException: Module with the Main dispatcher is missing. Add dependency providing the Main dispatcher, e.g. 'kotlinx-coroutines-android' and ensure it has the same version as 'kotlinx-coroutines-core'
	at kotlinx.coroutines.internal.MainDispatchersKt.throwMissingMainDispatcherException(MainDispatchers.kt:77)
	at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.missing(MainDispatchers.kt:108)
	at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.isDispatchNeeded(MainDispatchers.kt:92)
	at kotlinx.coroutines.test.internal.TestMainDispatcher.isDispatchNeeded(TestMainDispatcher.kt:31)
	at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:315)
	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:26)
	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:21)
	at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:88)
	at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:123)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:52)
	at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:43)
	at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
	at org.jesperancinha.ktd.MainScopeLauncher$Companion.runMainCoroutinesTest(MainScopeLauncher.kt:20)
	at org.jesperancinha.ktd.MainScopeLauncher$Companion.access$runMainCoroutinesTest(MainScopeLauncher.kt:10)
	at org.jesperancinha.ktd.MainScopeLauncher$Companion$main$1.invokeSuspend(MainScopeLauncher.kt:15)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:277)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:95)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:69)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:48)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at org.jesperancinha.ktd.MainScopeLauncher$Companion.main(MainScopeLauncher.kt:14)
	at org.jesperancinha.ktd.MainScopeLauncher.main(MainScopeLauncher.kt)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: null

Process finished with exit code 0
```

Remember to check the source for more details:

* [Kotlin lang - kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-main.html)

And if you have read this and have learned something new, you probably are ready to answer the following quiz:

{% embed https://youtube.com/shorts/VIITIP4-WWU?feature=share  %}
 

And you can check your answer in the response video I created:

{% embed https://youtube.com/shorts/vr8lVaF4EQw?feature=share %}

Have a good one everyone!