Сериализация JSON останавливает интерфейс - PullRequest
2 голосов
/ 06 апреля 2019

Я делаю проект Kotlin Multiplatform для Android и iOS. Моя цель состоит в том, чтобы выполнить сериализацию и сериализацию JSON в общем модуле и использовать эти данные на целевой платформе.

Но у меня есть проблема: он блокирует пользовательский интерфейс в приложении для iOS. Загрузка хороша, потому что она выполняется сетевой библиотекой, но когда JSON достаточно большой, а сериализация занимает некоторое время, пользователь останавливает интерфейс до тех пор, пока сериализация не будет завершена.

Вот мои шаги:

Общее

Метод запроса с использованием библиотеки 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()

Я предположил, что это должно выполняться асинхронно в основном потоке без блокировки пользовательского интерфейса.

Что я делаю не так? Я пытался использовать withContext при вызове сопрограммы, но это не помогло.

Есть ли способ выполнения сложных задач в общем модуле без блокировки пользовательского интерфейса на конкретной платформе?

Ответы [ 2 ]

2 голосов
/ 06 апреля 2019

Синтаксический анализ JSON является тяжелой задачей и должен выполняться в фоновом потоке. Вместо асинхронной отправки в основную очередь, асинхронно отправляйте ее в глобальную очередь.

1 голос
/ 06 апреля 2019

Как только ваш сетевой вызов завершится, ваш Json-анализ перейдет в основной поток.Это заблокирует все остальные вещи в главном потоке, включая пользовательский интерфейс.Вам нужно отправить разбор Json в фоновый поток.Вот несколько примеров параллелизма с мультиплатформой kotlin

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

...