Kotlin 协程延迟在 IOS 队列调度器上不起作用

问题描述

我有一个 KMM 应用程序,并且有代码

fun getWeather(callback: (WeatherInfo) -> Unit) {
        println("Start loading")
        GlobalScope.launch(Applicationdispatcher) {
            while (true) {
                val response = httpClient.get<String>(API_URL) {
                    url.parameters.apply {
                        set("q","Moscow")
                        set("units","metric")
                        set("appid",weatherApiKey())
                    }
                    println(url.build())
                }
                val result = Json {
                    ignoreUnkNownKeys = true
                }.decodeFromString<WeatherApiResponse>(response).main
                callback(result)

                // because Applicationdispatcher on IOS do not support delay
                withContext(dispatchers.Default) { delay(DELAY_TIME) }
            }
        }
    }

如果我用 withContext(dispatchers.Default) { delay(DELAY_TIME) } 替换 delay(DELAY_TIME),执行永远不会返回到 while 循环,它将只有一次迭代。

IOS 的 Applicationdispatcher 看起来像:

internal actual val Applicationdispatcher: Coroutinedispatcher = NsQueuedispatcher(dispatch_get_main_queue())

internal class NsQueuedispatcher(
    private val dispatchQueue: dispatch_queue_t
) : Coroutinedispatcher() {
    override fun dispatch(context: CoroutineContext,block: Runnable) {
        dispatch_async(dispatchQueue) {
            block.run()
        }
    }
}

delay代码我可以猜到,应该返回 DefaultDelay 并且应该有类似的行为,有/没有 withContext(dispatchers.Default)

/** Returns [Delay] implementation of the given context */
internal val CoroutineContext.delay: Delay get() = get(ContinuationInterceptor) as? Delay ?: DefaultDelay

谢谢!

附言我收到了 ktor-samplesApplicationdispatcher

解决方法

可能 ApplicationDispatcher 是一些旧东西,你不需要再使用它了:

CoroutineScope(Dispatchers.Default).launch {

}

MainScope().launch {

}

不要忘记使用 -native-mt 版本的协程,更多信息在此 issue