Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin Coroutines with returning value

I want to create a coroutine method which has returning value.

For example)

fun funA() = async(CommonPool) {     return 1 }  fun funB() = async(CommonPool) {     return 2 }  fun sum() {     launch {         val total = funA().await() + funB().await()     } } 

If I want to return total in sum method, how should I do?

like,

fun sum(): Int {     launch {         val total = funA().await() + funB().await()     }         return total } 
like image 582
Expert wanna be Avatar asked Nov 01 '17 13:11

Expert wanna be


People also ask

How do you return a value from coroutines?

Put a yield at the end of your coroutine with the value you want to return... Invoke it and get the return value using the utility class... public void Start()

What are the two ways to make a coroutines computation code cancellable?

There are two approaches to making computation code cancellable. The first one is to periodically invoke a suspending function that checks for cancellation. There is a yield function that is a good choice for that purpose. The other one is to explicitly check the cancellation status.

What is deferred in Android?

Deferred value is a non-blocking cancellable future — it is a Job with a result. It is created with the async coroutine builder or via the constructor of CompletableDeferred class. It is in active state while the value is being computed.

What does async do in Kotlin?

Creates a coroutine and returns its future result as an implementation of Deferred. The running coroutine is cancelled when the resulting deferred is cancelled.


2 Answers

To return exactly Int, you need to get out of the coroutine world and that's what runBlocking is for:

fun sum(): Int = runBlocking {     funA().await() + funB().await() } 

See Bridging blocking and non-blocking worlds in the coroutine guide, and Composing suspending functions for how to do it if you want to use sum inside coroutines.

like image 86
Alexey Romanov Avatar answered Sep 19 '22 04:09

Alexey Romanov


It may be late to answer this question but hopefully someone will find it useful. The code snippet below calculates sum of 3 values A + B + C. Each value is calculated independently in its own background thread in parallel and then all interim results consolidated into one final result and returned to the main thread to display it on a screen.

So it takes 5 seconds to calculate the final value (not 10 seconds = 2 + 3 + 5) and the result is 6 obviously and it's non-blocking, the main thread can handle other events while sum() execution is not complete.

suspend fun sum(scheduler: ThreadPoolExecutor): Int = coroutineScope {      withContext(scheduler.asCoroutineDispatcher()) {         val a = async { funA() }         val b = async { funB() }         val c = async { funC() }          a.await() + b.await() + c.await()     } }  fun funA(): Int {     Thread.sleep(2000L)     return 1 }  fun funB(): Int {     Thread.sleep(3000L)     return 2 }  fun funC(): Int {     Thread.sleep(5000L)     return 3 }  class MainActivity : AppCompatActivity(), View.OnClickListener {     private val tripletsPool = ThreadPoolExecutor(3, 3, 5L, TimeUnit.SECONDS, LinkedBlockingQueue())     ...      override fun onClick(view: View?) {         if (view == null) {             return         }          when (view.id) {             R.id.calculate -> {                 GlobalScope.launch(Dispatchers.Main, CoroutineStart.DEFAULT) {                     progressBar.visibility = View.VISIBLE                     result.setText("${sum(tripletsPool)}")                     progressBar.visibility = View.GONE                 }             }         }     } } 
like image 44
Aleksei Mulin Avatar answered Sep 19 '22 04:09

Aleksei Mulin