androidkotlinkotlin-coroutines

How to build list from async tasks properly in Kotlin


I have function like this

fun getUsersList(userIds: List<String>): List<User> {

    val list = mutableListOf<User>()

    userIds.forEach { id ->
        getUserFromDatabase(id) { user ->
            list.add(user)
        }
    }

    return list
}

Ofcourse in this case method return empty list cos it call return list before async tasks in cycle is completed.
So how to make it wait until cycle will be completed before return?
I learned coroutine basics but still have no idea how to handle this, that's why i'm using callbacks to update viewModel.

UPD: To clarify my situation, I get (for example) List<Type1> from database and from this list get userId's and after that get User's from database. I need to build Map<Type1,User> and put it in viewModel. For that I use:

list<Type1>.forEach { type1 -> 
        getUserFromDatabase(type1.userId) { user ->
            map.put(type1, user)
        }
    }

Actually question was about returning result instead of callbacks and I got the answer. Further I'll handle it myself. Thank you all.


Solution

  • Build a List<Deferred<User>> and then call awaitAll() on it to get the resulting List<User>. All of that must be happening in a CoroutineScope - in my example it is created with coroutineScope, but you can use withContext or some other way.

    suspend fun getUsersList(userIds: List<String>): List<User> = coroutineScope {
        buildList {
            userIds.forEach { id ->
                add(async {
                    getUserFromDatabase(id)
                })
            }
        }.awaitAll()
    }