Могу ли я получить фактическую стоимость возврата, если использую запуск в Котлине?

Я изучаю сопрограммы Котлина.

Код A использует async в сопрограммах Kotlin, и я могу использовать .await() для отложенного значения, чтобы получить его конечный результат, поэтому one.await() вернет Int.

Если я использую launch в сопрограммах, могу ли я получить фактическое значение так же, как one.await()?

Код А

val time = measureTimeMillis {
    val one = async { doSomethingUsefulOne() }
    val two = async { doSomethingUsefulTwo() }
    println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")       

suspend fun doSomethingUsefulOne(): Int {
    delay(1000L) // pretend we are doing something useful here
    return 13
}

suspend fun doSomethingUsefulTwo(): Int {
    delay(1000L) // pretend we are doing something useful here, too
    return 29
}

person HelloCW    schedule 19.03.2020    source источник
comment
Почему ты? Вся суть существования этих двух вещей, async и launch, заключается в том, что одна предназначена для вычислений, которые возвращают значение, а другая - для работы, вызывающей побочные эффекты.   -  person Marko Topolnik    schedule 19.03.2020


Ответы (3)


Не существует [стандартного нестандартного] способа получить результат от launch. В этом весь смысл async.

Две функции launch и async имеют ровно одно различие, а именно, что launch запускает и забыл, а async позволяет дождаться результата.

Следовательно, у вас не должно быть причин использовать launch вместо async, если только вам не нужен результат, поэтому вопрос довольно неожиданный.

person Joffrey    schedule 19.03.2020

Если вы используете launch, «фактическое значение» будет Unit, как вы можете видеть из подпись

fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job (source)

так что вам даже не нужно его запускать.

Если вы передадите лямбду в launch, как в

launch { doSomethingUsefulOne() }

это правда

launch { doSomethingUsefulOne(); Unit }

и значение doSomethingUsefulOne() выбрасывается.

person Alexey Romanov    schedule 19.03.2020

Короткий ответ: НЕТ.

Как вы указали, async и await дадут вам результат.

Но Launch используется для другой цели. Его цель - действовать как мост между мирами Coroutine и NonCoroutine.

Рассмотрим пример ViewModel, мир сопрограмм которой управляется viewModelScope

fun nonCoroutineWorldFunction() {
 ....
 ....
 viewModelScope.launch { 
   // runs in coroutine world
 }
 ....
 ....
 viewModelScope.launch { 
   // runs in coroutine world
 }


}

Launch можно считать чем-то похожим на FIRE AND FORGET. Вы просто запускаете его, чтобы он выполнял свою работу, а не ждете, пока он выполнит свою работу.

person Anup Ammanavar    schedule 19.03.2020
comment
Его можно использовать для этого, но он также отлично подходит для использования в мире сопрограмм. - person Alexey Romanov; 19.03.2020
comment
Да я согласен. В этом конкретном случае я всего лишь пытался объяснить разницу между async и launch, где запуск обычно означает выстрелил и забыл. - person Anup Ammanavar; 19.03.2020