https://kotlinlang.org logo
#coroutines
Title
# coroutines
r

Rob

01/07/2021, 2:36 PM
Is there an operator to combine the latest values from a
List<Flow<T>>
? Something that would have this signature
(List<Flow<T>>) -> Flow<List<T>>
? I’m updating a RecyclerView using
AsyncListDiffer.submitIList()
.
t

tateisu

01/07/2021, 2:52 PM
Flow is not a collection, so I think you'll have to implement a mechanism to remember recent values yourself.
r

Rob

01/07/2021, 2:52 PM
There are Rx operators for this transformation so I was hoping Flow came with batteries 😉
My first attempt.
m

MiSikora

01/07/2021, 3:29 PM
You can use something like this.
Copy code
internal fun <T> Iterable<Flow<T>>.combineLatest(): Flow<List<T>> {
  val emptyFlow = emptyFlow<List<T>>()
  return fold(emptyFlow) { xs, x ->
    if (xs === emptyFlow) {
      x.map(::listOf)
    } else {
      xs.combine(x) { a, b -> a + b }
    }
  }
}
r

Rob

01/07/2021, 4:07 PM
Impressive but it doesn’t quite behave correctly for me. I’m not sure why. My implementation also doesn’t work 😕
m

MiSikora

01/07/2021, 4:21 PM
What doesn't work? What is the incorrect behavior?
r

Rob

01/07/2021, 4:42 PM
For some reason I only get the first value after one of the flows completes.
I’m dealing with other bugs so it might not be this code
d

Dominaezzz

01/07/2021, 4:55 PM
I think you want
combine(....) {...}
.
r

Rob

01/07/2021, 6:55 PM
It works as expected. It was just stupid Retrofit/OkHttp blocking preventing multiple concurrent requests.
This is another version that works. But I don’t think these are efficient. Is there an implementation is easy to reason about and reasonably efficient?
d

Dominaezzz

01/07/2021, 8:09 PM
Copy code
fun <T> Iterable<Flow<T>>.combineLatest(): Flow<List<T>> = combine(this) { it.toList() }
👍 2
m

MiSikora

01/08/2021, 3:45 PM
Oh nice. I wasn’t aware of an overload that accepts an iterable.
5 Views