JSON 序列化冻结 UI

JSON serialization freezes the UI

我正在为 Android 和 iOS 制作一个 Kotlin Multiplatform 项目。我的目标是在公共模块中进行网络连接和 JSON 序列化,并在目标平台中使用该数据。

但我有一个问题:它阻止了 iOS 应用程序上的 UI。下载没问题,因为它是由网络库完成的,但是当 JSON 足够大并且序列化需要一些时间时,它会冻结 UI 直到序列化完成。

这是我的步骤:

普通

使用ktor库的请求方式:

class NetworkProvider {
    private val client = HttpClient()
    suspend fun request(urlString: String): String {
        return client.request<String>(urlString)
    }
}

具有JSON序列化的请求方法:

suspend fun request(): CustomObject {
    val json = networkProvider.request("API endpoint")
    val object = Json.nonstrict.parse(CustomObject().serializer(), json)
    return object
}

执行请求:

class Downloader {
    var listener: DownloadListener? = null
    fun download() {
        CustomCoroutineScope().launch {
            val object = request()
            listener?.onCompleted(object)
        }
    }
}

调度程序和协程范围:

class UIDispatcher : CoroutineDispatcher() {
    override fun dispatch(context: CoroutineContext, block: Runnable) {
        dispatch_async(dispatch_get_main_queue()) {
            block.run()
        }
    }
}

internal class CustomCoroutineScope : CoroutineScope {
    private val dispatcher = UIDispatcher()
    private val job = Job()
    override val coroutineContext: CoroutineContext
        get() = dispatcher + job
}

iOS

实现DownloadListener方法:

func onCompleted(object: CustomObject) {
    // Update the UI
 }

并调用请求

downloader.download()

我假设它应该在主线程中异步执行而不阻塞UI。

我做错了什么?我在调用协程时尝试使用 withContext 但它没有帮助。

有没有办法在通用模块中做繁重的任务而不阻塞特定平台的UI?

网络调用完成后,Json 解析将在主线程结束。这将阻塞主线程上的所有其他内容,包括 ui。您需要将 Json 解析发送到后台线程。下面是一些与 kotlin 多平台并发的例子

https://github.com/touchlab/DroidconKotlin/blob/master/sessionize/lib/src/commonMain/kotlin/co/touchlab/sessionize/platform/Functions.kt

JSON 解析是一项繁重的任务,需要在后台线程上完成。不是在主队列上异步调度,而是在全局队列上异步调度。