admin 管理员组

文章数量: 887007

kotlin协程中使用Dispatchers.Main报错的问题

在刚开始接触kotlin协程的时候,使用Dispatchers.Main操作主线程可能会遇到错误Module with the Main dispatcher had failed to initialize. For tests Dispatchers.setMain from kotlinx-coroutines-test module can be used。这可能是在普通的kotlin项目中使用Dispatcher.Main造成的。

fun main() {GlobalScope.launch(Dispatchers.Main) {print("success")}
}

例如上面这段代码就会出现错误,因为kotlin协程中如果要操作主线程是有条件的,个人理解为需要在一些在主线程中操作UI的项目中才可以使用Dispatcers.Main。

/** In order to work with `Main` dispatcher, the following artifacts should be added to project runtime dependencies:*  - `kotlinx-coroutines-android` for Android Main thread dispatcher*  - `kotlinx-coroutines-javafx` for JavaFx Application thread dispatcher*  - `kotlinx-coroutines-swing` for Swing EDT dispatcher** In order to set a custom `Main` dispatcher for testing purposes, add the `kotlinx-coroutines-test` artifact to * project test dependencies.*/@JvmStaticpublic actual val Main: MainCoroutineDispatcher get() = MainDispatcherLoader.dispatcher

从以上的部分注释可以看出如果需要操作主线程的话可以使用 android项目swing项目javafx项目,并且引入相对应的运行时依赖。

可以看出操作主线程是与平台相关的。在MainDispatcherLoader中能够发现一些端倪。

// Lazy loader for the main dispatcher
internal object MainDispatcherLoader {private val FAST_SERVICE_LOADER_ENABLED = systemProp(FAST_SERVICE_LOADER_PROPERTY_NAME, true)@JvmFieldval dispatcher: MainCoroutineDispatcher = loadMainDispatcher()private fun loadMainDispatcher(): MainCoroutineDispatcher {return try {val factories = if (FAST_SERVICE_LOADER_ENABLED) {MainDispatcherFactory::class.java.let { clz ->FastServiceLoader.load(clz, clz.classLoader)}} else {//We are explicitly using the//`ServiceLoader.load(MyClass::class.java, MyClass::class.java.classLoader).iterator()`//form of the ServiceLoader call to enable R8 optimization when compiled on Android.ServiceLoader.load(MainDispatcherFactory::class.java,MainDispatcherFactory::class.java.classLoader).iterator().asSequence().toList()}factories.maxBy { it.loadPriority }?.tryCreateDispatcher(factories)?: MissingMainCoroutineDispatcher(null)} catch (e: Throwable) {// Service loader can throw an exception as wellMissingMainCoroutineDispatcher(e)}}
}

我们可以看到在loadMainDispatcher函数中使用了MainDispatcherFactory::class.java,获取到了该类的Javaclass 对象,而该对象在不同平台上是不同的。在android项目中该对象就是kotlinx.coroutines.android.AndroidDispatcherFactory类的Javaclass对象。在普通项目中Dispatchers.Main是不能被成功的初始化的,所以会出现这个问题。然而其他的几个适配器是可以被使用的,这种设计应该主要是因为Dispatchers.Main的作用就是要在主线程中操作UI,防止UI阻塞,如果没有UI的话就没有必要使用它了。

本文标签: kotlin协程中使用DispatchersMain报错的问题