3

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)
        }
    }
}

Dispatcher とコルーチンのスコープ:

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 をブロックすることなく、共通モジュールで重いタスクを実行する方法はありますか?

4

2 に答える 2