Hi everyone :slightly_smiling_face: I have a compl...
# flow
j
Hi everyone 🙂 I have a complicated flow use case and I have no idea what’s the best solution. Basically, we have 3 flows that emit at different intervals. 2 that emit rather quickly (eg every 10ms) and 1 slower (~every 70ms). What I want to do is emit at very fixed interval inbetween, let’s say 50ms So every 50ms, we emit a combination of the latest value from each flow. What we have done in the past for similar use cases is a sort of ticker flow with the
combine
operator but it doesn’t quite fit here Any idea how we could do that? Thanks! 🙏
I’m thinking more about it 🤔 Maybe a big
combine
with all 3 flows then
debounce
at 50ms would work?
l
I think debounce would not emit anything if the underlying flows emit more frequently than the debounce timeout. A "throttle" operation is more what you are looking for, check out this answer for starters: coroutine - Kotlin Flow only collect every second - Stack Overflow
j
looks like you are correct, missed it in the documentation:
Note that the resulting flow does not emit anything as long as the original flow emits items faster than every timeoutMillis milliseconds.
trying to play with flowmarbles and tbh, i’m kinda confused by all this operators 😅 there’s also
sample
available or your suggestion which I will try 🤔
g
It seems like you’re looking for the zip operation.
combine
simply appends the two flows, but zip emits the items accordingly to their index, until both values from both indexes are emitted, the flow is backpressured:
Copy code
data class Num(
    val english: String,
    val spanish: String,
    val portuguese: String,
)

val englishFlow = flowOf("one", "two", "three", "four").onEach { delay(10) }
val spanishFlow = flowOf("un", "dos", "tres", "cuatro").onEach { delay(10) }
val portugueseFlow = flowOf("um", "dois", "três", "quatro").onEach { delay(70) }

val threeLanguagesFlow: Flow<Num> = 
    englishFlow
        .zip(spanishFlow) { english, spanish -> english to spanish } // Flow<Pair<String, String>>
        .zip(portugueseFlow) { (english, spanish), portuguese -> Num(english, spanish, portuguese) }
Once you collect
threeLanguagesFlow
, the result will be:
Copy code
Num(english=one, spanish=un, portuguese=um)
Num(english=two, spanish=dos, portuguese=dois)
Num(english=three, spanish=tres, portuguese=três)
Num(english=four, spanish=cuatro, portuguese=quatro)
Not entirely sure if that’s what you’re looking for, but, I hope it helps, @Jérémy CROS. 🙂
j
hmmm, let me see if I understand this correctly 🤔 In your example, one en/es is not emitted until one pl is emitted too, correct? I think that’s “too slow” if that make sense 😅 What I need is to emit every fixed interval the latest from each flow, whatever the value may be, even if some values are repeated from the previous emission. What I ended up doing is
combine
all 3 flows, map the data, emit the value then
sample
on the period (50ms in my case). That seemed to work pretty well in practice 🙂 But thanks for your detailed answer! I’m not super familiar with zip and it could prove useful for another use case 🙏
g
Oh, I see! Glad you found the solution!