Recently I discovered a flow behaviour that I couldn't understand.
Consider this situation:
you have a parent flow
and inside its collect
, you'll have a "child" flow
and calling .collect()
, like this:
parentFlow.collect {
childFlow.collect()
}
Then if the parentFlow emits some values, the childFlow.collect()
will not be called.
By doing some searches on SO I found the following questions are similar to mine:
However I intend to dig deeper about what's the reason behind this behaviour, therefore I have created a project to reliably reproduce it, you can check it out on github: https://github.com/dumbfingers/Playground/tree/flow-inside-flow
In this mini-repro, I have put some log output. When you click the button, the expect log output should be:
Test: onArrayUpdated
Test: item: {some number}
Test: item: {some number}
Test: onFlowChanged
Test: repoObserve delayed
Test: item: {some number}
Test: item: {some number}
Test: repoAnotherObserve delayed
However, the actual result is:
Test: onArrayUpdated
Test: item: {some number}
Test: item: {some number}
Which indicates these two collect
call inside the randomFlow
are not called:
repository.repoObserve(list).collect {
repository.repoAnotherObserve().collect()
}
In this SO: Android: collecting a Kotlin Flow inside another not emitting The answer suggested that "collecting infinite flow" cause this issue.
And in my experiment, either
repoObserve
and repoAnotherObserve
to suspend
method and making them not returning a flowor
combine
to combine these flowswill solve this problem.
But why does collect flow inside another flow's collect won't work?
You can launch a Coroutine inside parent collect { ... } block
val scope: CoroutineScope = ...
parentFlow.collect {
scope.launch {
childFlow.collect()
}
}
or
parentFlow.flatMapMerge { childFlow }.collect {
// logic here ...
}
You can also replace flatMapMerge
with flatMapLatest
/flatMapConcat
/flatMapFirst
(FlowExt library)
Hope to help you
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With