If i have three flows that return boolean, what is...
# coroutines
m
If i have three flows that return boolean, what is the best operator equivalent to this: (if(aaa || bbb || ccc) ?
meaning, if a flow returns true along the way, use it. otherwise use the next
i can do it with chained flatMapLatest, but it seems weird
basically this
firstFlow
.flatMapLatest { condition ->
if (condition) {
flowOf(true)
} else {
secondFlow
.flatMapLatest { condition ->
if (condition) {
flowOf(true)
} else {
thirdFlow
}
}
}
}
c
Is your flow aaa a completing flow? And are you looking for it to complete before moving on to the next one?
m
i don’t want want to use combine, because only one flow may be needed
it doesn’t complete, no
r
And it’s required that if
firstFlow
emits again once
secondFlow
is started you need to cancel
secondFlow
and maybe restart it (if still false)?
That’s what you’re currently getting with `flatMapLatest`; if you don’t need/ want that then things are much simpler
l
Sounds like you'd want
combine
but I'm not sure I understood what you want to do.
m
Emit true if any of the flows emit true, minimizing flow collection. combine just works, but it collect the three needlesslly
l
You mean, you only care about the first value?
If so, it seems like you want to write
flowA.first() || flowB.first() || flowC.first()
m
Wont work, the flows change
At any time, any1 can change to true.
Ill just use combine and shut up :p
r
Surely
merge
is more appropriate than
combine
?
At least that way you don’t have to wait for all flows to emit something?
m
Good point. Thanks
l
Another idea:
Copy code
raceOf({
    flowA.first { it }
}, {
    flowB.first { it }
}, {
    flowC.first { it }
})
With
raceOf
as defined at the end of this article: https://blog.louiscad.com/coroutines-racing-why-and-how
m
The resulting boolean is hot, not the first true
s
So
merge
makes sense but I don't understand your point here:
but it collect the three needlesslly
merge
would still collect all 3 so it can emit the latest value from any of them.
in other words, (A) you want 'one to win' and avoid waiting for that 'round' of booleans from all 3, or (B) which one 'wins' doesn't matter but you'll always be collecting from all three. It seems like you want (B) but then you mentioned that being inefficient and you wanted (A)?
n
The original solution with flatMapLatest seems to be the best. It will look less weird if you avoid indenting the third flow, just chain it - first.or(second).or(third) (assuming you make an or operator that uses flatMapLatest)
r
I still don't really get the reasoning for wanting to delay collecting flows
Can you actually guarantee that one flow will be significantly faster than another?
If not, just merge them all and let the first one win
Even if so, the first one will win anyway (and others will be cancelled) so doesn't really matter
m
merge won’t work. how do you single out the first ‘true’ using merge ? It’s a hot flow. Not only the first value is relevant
r
merge().filter(it).first()
m
it is a hot flow! It cannot call first
the value can change
i’ll describe with a more realistic usecase 1s
Let’s say you have three queries: a) has apples (true/false), b) has oranges (true/false), c) has grapes (true/false). You want to observe ‘hasFruit’. You can combine the three, but if the first one returns true, you don’t need the second or the third. (combine will do it, i was just asking if there is a better approach)
r
Ah yeah, if you need the case where they go back to (false, false, false) then you'll need to wait for all of them
But depending on how the flows are implemented I'd expect the combine version would still perform better than the flatMapLatest version
Also depends on how often they change and how often they're true
l
I get your use case now @myanmarking. The thing is that to get to what you want, you'll need to trade latency and/or correctness for efficiency. It also depends on how long it takes for one of your flows to produce a value when they're subscribed to. If you have that info, it can be helpful for the specific flow operator you want to do.