Return value from coroutines

from the CommonsWare Community archives

At September 29, 2020, 11:34pm, vedy asked:

Hi Mark,
For a method that has coroutine scope that does work in the back ground, how can I get a return value?

So if 'm calling the following method to return a value (and not just hop back to the Dispatcher.Main to update values)

fun getWidgets() : Widgets {
    CoroutineScope(Dispatchers.IO).launch {
   //Call an API on a suspend method and return value : "widgets"
   }
return widgets
}

I looked around and it seems that I need to do async await() , do you have an example?

thanks


At September 29, 2020, 11:55pm, mmurphy replied:

For your particular approach, yes.

Not in an Android context, but I do in Elements of Kotlin Coroutines: https://klassbook.commonsware.com/lessons/Coroutine%20Basics/async.html. One of the many things that I have to do in that book is extend my async() material…


At September 30, 2020, 2:11am, vedy replied:

Thanks Mark,
Using your example here’s what I’ve tried to do in Android :

    private fun searchTeamEvents(teamName: String) : String {
    var value = ""
    val client = GamesClient()
    CoroutineScope(Dispatchers.IO).launch {
        try {
            val res = client.getTeam(teamName)
            val events = client.getGames(res.teams[0].idTeam.toInt())

            val deferred = GlobalScope.async(Dispatchers.Default) {
                events.teamResults[0].strEvent
            }
            value = deferred.await()
            
            withContext(Dispatchers.Main) {
                text.text = events.teamResults[0].toString()
            }
        } catch (exception: Exception) {
            withContext(Dispatchers.Main) {
                Log.d(TAG, "searchTeamEvents: " + exception.message)
            }
        }
    }
return value
}

But still when I call searchTeamEvents(“TeamName”) it still returns the empty string. It seems I’m not using the await() correctly.
How can I capture that value and return it when calling the method?


At September 30, 2020, 11:07am, mmurphy replied:

Well, sure. launch() is asynchronous. It is almost guaranteed that searchTeamEvents() will return before the launched coroutine executes.

You would need to make searchTeamEvents() a suspend function and reorganize your code to take advantage of that, so you can get rid of launch() from searchTeamEvents() and move it into whatever calls searchTeamEvents().

FWIW, please note that across my books I have many samples of using coroutines in Android, and none are using them like this.


At September 30, 2020, 2:55pm, vedy replied:

That worked great, thanks Mark. And thanks for mentioning the treasure troves in the book, I was just going of the above Klassbook example.