【问题标题】:KMM on iOS: There is no event loop. Use runBlocking { ... } to start oneiOS 上的 KMM:没有事件循环。使用 runBlocking { ... } 启动一个
【发布时间】:2021-06-29 05:19:39
【问题描述】:

我正在尝试在 Kotlin Multiplatform 项目中使用 coroutines。我都没有这方面的经验。

我正在尝试调用这个函数

fun startFlow {
    coroutineScope.launch { 
        withContext(defaultDispatcher) {
           myFlow.collect { next -> onNext(next) }
        } 
    }
}

coroutineScope on iOS 是这个

val defaultScope: CoroutineScope = object : CoroutineScope {
    override val coroutineContext: CoroutineContext
        get() = SupervisorJob() + Dispatchers.Default
}

这不是给我这个问题的唯一调用,事实上所有对coroutines 的调用似乎都因这个错误而失败:

kotlin.IllegalStateException: There is no event loop. Use runBlocking { ... } to start one.

这就是我导入库的方式

val commonMain by getting {
        dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
        }
    }

我正在使用Kotlin 1.4.31。这个问题只存在于iOSAndroid 完美运行。

我不明白我是否遗漏了什么。

【问题讨论】:

    标签: kotlin-coroutines kotlin-multiplatform kotlin-multiplatform-mobile


    【解决方案1】:

    对于 iOS,您需要使用后缀为“native-mt”的协程,更多信息here

    所以用

    替换你的导入
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt")
    

    另请注意,根据documentation

    当使用也依赖于kotlinx.coroutines 的其他库时,例如Ktor,请确保指定kotlinx-coroutines 的多线程版本。你可以通过strictly 做到这一点:

    implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt"){
        version {
            strictly("1.5.2-native-mt")
        }
    }
    

    附言新的原生并发模型available 用于预览。查看New memory model migration guide。在此功能发布后,将不再需要 native-mt 后缀。

    【讨论】:

    • 在协同程序的 GitHub 存储库上,它说如果您对公共源集具有通用依赖项,它将导入特定于平台的版本。我虽然不需要后缀
    • 我已经用官方文档替换了一个链接,它描述了为什么我们仍然需要使用它。不久 - 他们仍在努力。此外,您还可以找到如何严格使用版本,以防您的其他依赖项依赖于协程
    • 未捕获的 Kotlin 异常:kotlin.native.IncorrectDereferenceException:非法尝试从其他线程访问非共享 @300b968 在添加严格函数后我现在得到了这个。
    • @BoldijarPaul 这是另一个问题。查看 Kotlin Native 并发模型在 documentation 中的工作原理。很快,您就不能在共享代码中使用var(没有原子包装器),但是当您需要在创建新对象时调用froze 时也会遇到问题。您问题中的代码似乎不会导致此类异常。您可以使用更多详细信息/堆栈跟踪以及相关代码更新您的问题,以防您在文档中找不到答案。
    【解决方案2】:

    您也可以使用常规的coroutines 库,但是您需要创建一个自定义的CoroutineDispatcher,将任务发布到mainRunLoop,例如:

    object NSLooperDispatcher: CoroutineDispatcher() {
        override fun dispatch(context: CoroutineContext, block: Runnable) {
            NSRunLoop.mainRunLoop.performBlock {
                block.run()
            }
        }
    }
    
    // use custom dispatcher
    withContext(NSLooperDispatcher) {
        myFlow.collect { next -> onNext(next) }
    } 
    
    

    协程的native-mt 分支明确指出切换线程存在问题,因此使用它可能仍然是一个好主意。否则,您将被限制在一个主线程上。

    【讨论】:

      猜你喜欢
      • 2020-04-09
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 2023-01-04
      • 1970-01-01
      • 2013-03-21
      • 1970-01-01
      • 2014-07-18
      相关资源
      最近更新 更多