I have a question about Kotlin flow. Basically what I want is that I want to enjoy the benefit of parallelism of merge()
, while also want to preserve the orders of flows.
Here is a use case. Let’s say there are two network APIs:
- one is to get a list of IDs; and
- the other one is given an ID, get an user
I what to
- Use the 1st API to get the IDs
- Use the 2nd API to get all the users
- Return the list of the users to UI for display (e.g. on Android)
To me, this looks like a perfect use case for Kotlin flows. I would probably do it like this:
// NetworkApi.kt
interface NetworkApi {
@GET("ids")
suspend fun getIds(): List<Int>
@GET("users/{id}")
suspend fun getUser(id: Int): User
}
And here is how I would call these APIs, using flow:
val usersFlow = flow {
emit(networkApi.getIds())
}.flatMapConcat { // it: List<Int>
val flowList = mutableListOf<Flow<User>>()
val userList = mutableListOf<User>()
for (id in it) {
flowList.add(flow{ emit(networkApi.getUser(id)) })
}
flowList.merge().toList(userList)
userList
}
Note that I used merge()
because I want to send the user requests ASAP in parallel, rather than one after another.
However, according to the documentation of merge()
, it will NOT be “preserving an order of elements”.
Is there a way to have both: parallelism and preserved order?
Thanks!