I have a flow that I use `.collect {}` on, however...
# coroutines
j
I have a flow that I use
.collect {}
on, however, I want to wait for a StateFlow/Boolean to be true before the collection can proceed, what is the recommended way of currently handling this? (None of the emits can be dropped, they need to wait for the StateFlow/Boolean to be true and emit as soon as it changes)
s
Copy code
flow {
   stateFlow.first { it == true }
     
     originalFlow.collect(this)
}
You can create a new flow, that awaits the first
true
signal from
StateFlow
and then it collects the original flow.
j
Thanks for the pointer, i'll check it out
j
@simon.vergauwen I think the
collect()
that is chained after the
first()
call is a mistake/typo,
first()
is already a terminal operator
s
Thank you @Joffrey that is indeed a mistake then, I wrote this from memory.
u
stateFlow.filter { it == true }.take(1).flatMap { originalFlow }
j
Thanks people
Copy code
suspend fun <T> Flow<T>.waitForTrue(stateFlow: StateFlow<Boolean>):Flow<T>{
    stateFlow.first { it }
    return this
}
Became the result, which seems kind of silly, but yeah
first
is suspending without being terminating, so it is a way to solve it.
j
The problem is that the operator that you created isn't cold anymore, it has to suspend at the moment it's called, instead of when the flow is collected
j
Is it a problem though? The only real effect I care about in this instance is that it block any
.collect
calls from proceeding?
The data is waiting to be collected is indeed put into a suspended state and will proceed when the stateFlow changes?
s
I’d say it’s a problem since now you’re waiting on stateFlow to constructor the
Flow
which has no influence on the collection.
1
j
And doing:
Copy code
suspend fun <T> Flow<T>.waitForTrue2(stateFlow: StateFlow<Boolean>): Flow<T> {
    return flow {
        stateFlow.first { it }
        this@waitForTrue2.collect(this)
    }
}
Would then adhere to this?
or must it basically be a replacement for
.collect
all together?
s
No, this is the replacement for
collect
. The lambda inside
flow { }
is executd when you call
collect
. So first it will await the boolean, and then it’ll collect the original flow.
j
Right, it makes sense
j
Your new version is fine (it's basically @simon.vergauwen's initial suggestion as an extension function), however you don't need the
suspend
keyword anymore 😉 Calling this operator immediately constructs the new flow without waiting. Collectors of this flow are the ones that will suspend when actually collecting
☝️ 1
👍 1
j
Allright, thanks for clearing things up 🙂