Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait and properly return value from async coroutine

I'm calling a function (non-suspended) from a button click. I want to run a loop in function using async coroutine and return last computed value.

My code :

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    btnCount.setOnClickListener {

        var result = GlobalScope.async { dummyFoo() }
        runBlocking {
            Toast.makeText(this@MainActivity, result.await().toString(), Toast.LENGTH_LONG).show()
        }
    }
}

private fun dummyFoo() : Int {
    var result : Int = 0
    val waitFor = CoroutineScope(Dispatchers.IO).async {
        for (i in 1..20000) {
            result++
        }
        return@async result
    }

    return result
}

Output :

I'm getting 0 in Toast.

I want 20000 in Toast.

How can I make my code to wait until loop completion and result to become 20000 and output it?

like image 262
Kushal Avatar asked Mar 02 '23 23:03

Kushal


2 Answers

You should use await in dummyFoo()

private suspend fun dummyFoo() : Int {
    var result : Int = 0
    val waitFor = CoroutineScope(Dispatchers.IO).async {
        for (i in 1..20000) {
            result++
        }
        return@async result
    }
    waitFor.await()
    return result
}
like image 108
Cuong Nguyen Avatar answered Mar 05 '23 15:03

Cuong Nguyen


It seems that you want to launch a CPU-intensive task off the GUI thread and then present the result in GUI. This is a basic use case of coroutines and it's solved as follows:

btnCount.setOnClickListener {
    GlobalScope.launch(Dispatchers.Main) {
        val result = withContext(Dispatchers.Default) {
            dummyFoo()
        }
        Toast.makeText(this@MainActivity, result.toString(), Toast.LENGTH_LONG).show()
    }
}

This goes with the usual warning that you should not launch coroutines in the global scope, instead create a scope for the activity in question. Otherwise these background tasks will hog the CPU even when the user switches away from your app.

like image 36
Marko Topolnik Avatar answered Mar 05 '23 15:03

Marko Topolnik