Приостановить асинхронную подфункцию kotlin coroutine

У меня есть асинхронный CoroutineScope, в котором может быть (по условию) вызов подфункции, которая возвращает свой результат в асинхронном Unit

Как я могу дождаться возвращенного результата и вернуть его вне асинхронного Unit. Поэтому дождитесь вызова Unit подфункцией.

Пример:

GlobalScope.launch {
    var value: Int = 0
    if (condition) {
        // the subFunction has a Unit<Int> as return type
        subFunction() { result ->
            value = result
        }
    }
    Log.v("LOGTAG", value.toString())
}

Как я могу дождаться завершения выполнения subFunction перед продолжением кода или напрямую присвоить значение результата переменной?

subFunction не должен быть suspend функцией, однако он может быть встроен во вспомогательную функцию.

(код должен работать в среде Android)


person Sebastian Schneider    schedule 31.07.2019    source источник
comment
Вы не можете этого сделать, если это не функция приостановки.   -  person Francesc    schedule 31.07.2019
comment
@Francesc можно ли каким-то образом создать локальную функцию supend, которая это обрабатывает? Я не могу изменить subFunction   -  person Sebastian Schneider    schedule 31.07.2019


Ответы (2)


Вы можете сделать это, преобразовав обратный вызов в функцию приостановки.

GlobalScope.launch {
    var value: Int = 0
    if (condition) {
        // the subFunction has a Unit<Int> as return type
        value = subFunctionSuspend()
    }
    Log.v("LOGTAG", value.toString())
}

suspend fun subFunctionSuspend() = suspendCoroutine { cont ->
    subFunction() { result ->
        cont.resume(result)
    }
} 
person Francesc    schedule 31.07.2019
comment
Спасибо, если я прав, вы также можете просто встроить subFunctionSuspend. но работает! - person Sebastian Schneider; 31.07.2019

Не очень красивое, но рабочее решение с каналами:

    GlobalScope.launch {
        val channel = Channel<Int>()
        if (condition) {
            // the subFunction has a Unit<Int> as return type
            subFunction() { result ->
                GlobalScope.launch {
                    channel.send(result)
                    channel.close()
                }
            }
        }
        for (i in channel) {
            println(i)
        }
    }
person Andrei Tanana    schedule 31.07.2019