Module with Main dispatcher is missing
Asked Answered
R

11

43

I'm trying to make a background call to my local database and update the UI with the results using coroutines. Here is my relevant code:

import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.Dispatchers.IO
import kotlinx.coroutines.experimental.Dispatchers.Main
import kotlin.coroutines.experimental.CoroutineContext
import kotlin.coroutines.experimental.suspendCoroutine

class WarehousesViewModel(private val simRepository: SimRepository)
: BaseReactViewModel<WarehousesViewData>(), CoroutineScope {

private val job = Job()

override val coroutineContext: CoroutineContext
    get() = job + Main

override val initialViewData = WarehousesViewData(emptyList())

override fun onActiveView() {
    launch {
        val warehouses = async(IO) { loadWarehouses() }.await()
        updateViewData(viewData.value.copy(items = warehouses))
    }
}

private suspend fun loadWarehouses(): List<Warehouse> =
    suspendCoroutine {continuation ->
        simRepository.getWarehouses(object : SimDataSource.LoadWarehousesCallback {
            override fun onWarehousesLoaded(warehouses: List<Warehouse>) {
                Timber.d("Loaded warehouses")
                continuation.resume(warehouses)
            }

            override fun onDataNotAvailable() {
                Timber.d("No available data")
                continuation.resume(emptyList())
            }
        })
    }
}

My problem is that I get a runtime exception:

java.lang.IllegalStateException: Module with Main dispatcher is missing. Add dependency with required Main dispatcher, e.g. 'kotlinx-coroutines-android'

I already added these to my gradle:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.30.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.26.0'

I'm a bit new to this, can someone help me?

Ricotta answered 6/10, 2018 at 9:31 Comment(1)
use the same versionsQuern
R
76

Using just the kotlinx-coroutines-android version solves the problem.

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.30.1'
Ricotta answered 6/10, 2018 at 11:41 Comment(7)
kotlinx-coroutines-core is a transitive dependency of kotlinx-coroutines-android and the proper solution is to remove it.Defense
Good catch Marko! Just to clarify, Marko means remove kotlinx-coroutines-core, it's included in kotlinx-coroutines-androidGalligaskins
To be use in Kotlin 1.3 must use this implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1'Kooky
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3' - is the most current if anyone wants to save a few seconds.Cheque
@MarkoTopolnik I am confused. It is NOT an Android project, but a plain Kotlin console project (the one that prints "hello world" in the command prompt), and I have added org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.0 as another answer had suggested, and I encountered this runtime error when trying to use Dispatchers.Main. So, I should use kotlinx-coroutines-android even if it is not an Android project? kotlinx-coroutines-core-jvm has been deprecated and should no longer be used?Scoff
@MarkoTopolnik I have tried switching to Android version, but it threw a new runtime exception: NoClassDefFoundError: android/os/LooperScoff
@DamnVegetables Indeed, don't try to use either kotlinx-coroutines-android or Dispatchers.Main outside of an Android application.Defense
F
18

You may be missing some Proguard rules.

I had the same problem in release build and solved it by adding the following rules:

-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-keepclassmembernames class kotlinx.** {
    volatile <fields>;
}

from https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/kotlinx-coroutines-android/example-app/app/proguard-rules.pro

Flaring answered 28/12, 2018 at 5:27 Comment(4)
That was it for my case. I've added all of the keeps form the GitHub page you've provided. Thank you very much!Misspell
The GitHub page linked is no longer available, 404's for meGormless
It doesn't matter cren90 . I want to share as example. You can simply follow what I mentionedFlaring
Can rather put it in consumer-rules.pro if the module is a libraryKnowing
C
11

Use both Core and Android dependency

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6'
Cephalad answered 9/5, 2020 at 22:5 Comment(1)
as pointed below the accepted answer, using only the android is enoughRicotta
A
10

If you're facing this problem with coroutines version 1.3.8, add this rule in your proguard-rules.pro:

-keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;}
Adept answered 10/8, 2020 at 12:23 Comment(1)
I run into this as well and indeed seems like the AndroidDispatcherFactory was not deobfuscated properly. With this in the proguard rules it worksIconoscope
B
4
./gradlew assembleDebug --rerun-tasks

fixes it if the above answers don't work for you (because you already had the required dependencies and you are using R8 which does not need the proguard rules).

Brigham answered 2/10, 2019 at 23:13 Comment(1)
I've just change for my flavor and all right! thanksCacilia
B
4

"core" is transitive dependency of "android" version in current version of "kotlinx-coroutines" so only use "android"

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0'
Batter answered 25/3, 2020 at 13:39 Comment(0)
G
3

Just an additional hint if anyone tries the solutions from above and they didn't work.

For me, --no-build-cache didn't help. Instead, a rule in proguard-rules.txt did the job:

-keep class kotlinx.coroutines.android.** {*;}

My setup is kotlinx-coroutines-android:1.3.9, no kotlinx-coroutines-core (I removed it as it turned out to be unnecessary), Kotlin 1.3.72, and Gradle 3.2.1.

Gratification answered 27/8, 2020 at 15:28 Comment(0)
A
3

I have fixed by doing both version same 'kotlinx-coroutines-android' and ensure it has the same version as 'kotlinx-coroutines-core'

// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5'//same as coroutines-android
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5"//same as coroutines-core
Astrict answered 2/10, 2020 at 17:47 Comment(0)
T
2

Well, in my case keeping minifyEnabled true was causing the issue. but to achieve the obfuscation it was mandatory for me to keep the minifyEnabled true on the release build. So I did the following changes.

//keep only 
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8'

in your proguard-rules.pro add

-keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;}

I also required to add the model classes used for API call via retrofit in the proguard-rules.pro

-keep class com.example.test.login.data.model.** { *; }
-keepclassmembers class com.example.test.login.data.model.** { *; }
Towhaired answered 27/11, 2020 at 7:57 Comment(0)
B
2

I got this error due to enabled proguard

-keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;}
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-keepclassmembernames class kotlinx.** {
   volatile <fields>;
}

Add above rules in proguard-rules.pro

Ballman answered 14/3, 2023 at 5:29 Comment(0)
K
0

This seems kind of an old issue but I'll document my case as it may help others: using Unity IAP @ 4.12.1 our app started to crash as soon we'd initialize the in-app purchase modules. This is due the Play Billing API changes on distribution

e.g.: the .aar is now injected through gradle dependency

Using Mujahid's awnser for gradle and Vishal's for proguard rules solved our case.

Useful notes

  • Remember to add both coroutines-android and coroutines-core at the same version
  • The version used in the latest Unity IAP 4.12.0 refers to PlayBilling 6.2.1 which depends on [email protected] Source
Kelcie answered 19/6 at 14:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.