Reputation: 2408
I have a data class, MyThing1
, which has an ID in it. data class MyThing1(val id: String)
I have another data class which we don’t care about its content, but let’s call it MyThing2
I have a function that returns a list of MyThing1
fun myEmitter1(): Flow<List<MyThing1>>
I have another Flow that takes in input an ID and returns a flow of objects, so
fun myEmitter2(id: String): Flow<MyThing2>
For each MyThing1
received from the flow, I want to combine it with the latest MyThing2
that gets emitted by myEmitter2
and return a Flow<List<CombinedThing>>
given the CombinedThing
is
data class CombinedThing(val myThing1: MyThing1, val myThing2: MyThing2) .
and where every times myThing1 changes, it observes myEmitter2(id)
and every time myThing2
emits, it emits a CombinedThing
.
In a diagram, I'd like something like this:
[mt11,mt12]--------------------------------------------------------------------------
observe for id 1 ----mt211-----------------------------------------------------------
--[observe for id 2]------------------------mt212-------------------------------------
---------------------[CT(mt11,mt211(1))]----[CT(mt11,mt211(1)),CT(mt2,mt212)]---------
Upvotes: 4
Views: 5419
Reputation: 10006
So the inputs to myEmitter2
should be the IDs of the values from myEmitter1
?
We could implement this with the flatMapLatest
and combine
operators:
myEmitter1().flatMapLatest { myThing1s: List<MyThing1> ->
val myThing2s: List<Flow<Pair<MyThing1 to MyThing2>> = myThing1s.map { t1 ->
myEmitter2(t1.id).map { t2 -> t1 to t2 }
}
combine(myThing2s) { combined: Array<Pair<MyThing1, MyThing2>> ->
combined.map { (t1, t2) -> CombinedThing(t1, t2) }
}
}
From the docs, flatMapLatest
creates "a flow that switches to a new flow produced by transform function every time the original flow emits a value". That fits your requirement that "every time myThing1
changes, it observes myEmitter2(id)
".
Inside flatMapLatest
's transform function, we see each list emitted by myEmitter1
. We use map
to turn the List<MyThing1>
into a list of flows. Each flow will take the values from myEmitter2
and use map
(again) to pair them up with the original myThing1
value. This gives us a List<Flow<Pair<MyThing1 to MyThing2>>
.
Finally, we use combine
to turn the list of flows into a Flow<List<CombinedThing>>
. The combine
operator takes a list of flows and emits values that are computed by combining the most recently emitted values from each flow. We get an array (I've called it combined
) containing the most recent value from each of our flows. Using map
, we can turn that array into a List
and turn our pair into a CombinedThing
object.
Upvotes: 7