Reputation: 8508
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?
Upvotes: 6
Views: 13713
Reputation: 200256
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.
Upvotes: 6
Reputation: 2982
Not sure I am seeing the purpose of this, but if that's what you want, replace Dispatchers.IO
with Dispatchers.Unconfined
Upvotes: 1
Reputation: 1018
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
}
Upvotes: 7