Котлин сопрограммы `runBlocking` - PullRequest
0 голосов
/ 14 сентября 2018

Я изучаю соплины Kotlin. Я читал, что runBlocking - это способ соединить синхронный и асинхронный код. Но какой прирост производительности, если runBlocking останавливает поток пользовательского интерфейса? Например, мне нужно запросить базу данных в Android:

    val result: Int
    get() = runBlocking { queryDatabase().await() }

private fun queryDatabase(): Deferred<Int> {
    return async {
        var cursor: Cursor? = null
        var queryResult: Int = 0
        val sqlQuery = "SELECT COUNT(ID) FROM TABLE..."
        try {
            cursor = getHelper().readableDatabase.query(sqlQuery)
            cursor?.moveToFirst()
            queryResult = cursor?.getInt(0) ?: 0
        } catch (e: Exception) {
            Log.e(TAG, e.localizedMessage)
        } finally {
            cursor?.close()
        }
        return@async queryResult
    }
}

Запросы к базе данных остановят основной поток, поэтому кажется, что это займет столько же времени, сколько и синхронный код? Пожалуйста, поправьте меня, если я что-то упустил.

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

runBlocking - это способ соединить синхронный и асинхронный код

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

runBlocking - это почти никогда инструмент, который вы используете в производстве. Это отменяет асинхронную, неблокирующую природу сопрограмм. Вы можете использовать его, если у вас уже есть некоторый код на основе сопрограмм, который вы хотите использовать в контексте, где сопрограммы не предоставляют никакого значения: при блокировке вызовов. Одним из типичных применений является тестирование JUnit, где метод тестирования должен просто сидеть и ждать завершения сопрограммы.

Вы также можете использовать его, играя с сопрограммами, внутри вашего main метода.

Неправильное использование runBlocking стало настолько распространенным, что команда Kotlin фактически попыталась добавить отказоустойчивую проверку, которая немедленно вызвала бы сбой вашего кода, если вы вызовете его в потоке пользовательского интерфейса. К тому времени, когда они это сделали, он уже взломал столько кода, что им пришлось его удалить.

0 голосов
/ 14 сентября 2018

На самом деле вы используете runBlocking для вызова приостановленных функций в «блокирующем» коде, который в противном случае не был бы вызван там или другими словами: вы используете его для вызова suspend функций вне сопрограммыcontext (в вашем примере блок, переданный в async, является функцией suspend).Кроме того (более очевидно, поскольку само название уже подразумевает), вызов тогда является блокирующим вызовом.Таким образом, в вашем примере это выполняется так, как если бы не было чего-то вроде async.Он ожидает (блоки прерывисто ), пока все в runBlocking -блоке не будет завершено.

Например, предположим, что функция в вашей библиотеке выглядит следующим образом:

suspend fun demo() : Any = TODO()

Этот метод не может быть вызван, например, main.Для такого случая вы используете runBlocking тогда, например:

fun main(args: Array<String>) {
  // demo() // this alone wouldn't compile... Error:() Kotlin: Suspend function 'demo' should be called only from a coroutine or another suspend function
  // whereas the following works as intended:
  runBlocking {
    demo()
  } // it also waits until demo()-call is finished which wouldn't happen if you use launch
}

Что касается повышения производительности: на самом деле ваше приложение может быть скорее более отзывчивым, чем более производительным (иногда также более производительным, например, если у вас несколькопараллельные действия вместо нескольких последовательных).Однако в вашем примере вы уже блокируете при назначении переменной, поэтому я бы сказал, что ваше приложение еще не стало более отзывчивым.Возможно, вы захотите вызвать свой запрос асинхронно, а затем обновить интерфейс, как только ответ станет доступен.Таким образом, вы просто опускаете runBlocking и используете что-то вроде launch.Вас также может заинтересовать Руководство по программированию пользовательского интерфейса с сопрограммами .

...