https://kotlinlang.org logo
Title
a

AmrJyniat

07/28/2022, 9:07 AM
Is there a real way to recollect the
Flow
each x seconds? like:
val flow = flow {
    emit(doApiCall())
}
.onEach{ delay(1000) }// something like that
........
flow.collect{
  //get flow value
}
I searched a lot but it seems that I need to put the code in fun and call it each time, what do you think?
e

ephemient

07/28/2022, 9:17 AM
is this what you want?
flow {
    while (true) {
        emit(doApiCall())
        delay(1000)
    }
}
a

AmrJyniat

07/28/2022, 9:37 AM
This works, but I look for an intermediate operator to apply on flow directly(like my example) because in some cases I receive a ready-flow(so there is no flow builder) from repo and pass it to the fragment.
e

ephemient

07/28/2022, 10:16 AM
in that case you can just wrap the flow in another,
fun <T> Flow<T>.repeatWhen(suspend predicate: suspend FlowCollector<T>.() -> Boolean): Flow<T> = flow {
    do {
        yieldAll(this@repeatWhen)
    } while (predicate())
}
::doApiCall.asFlow()
    .repeatWhen {
        delay(1000)
        true
    }
a

AmrJyniat

07/28/2022, 11:06 AM
I don't see
yieldAll()
fun in this scope, Although I tested
yield()
but didn't worked
e

ephemient

07/28/2022, 11:27 AM
my bad, it's
emitAll
a

AmrJyniat

07/28/2022, 11:33 AM
Thanks it's working now, but I wonder if there is any negative side on performance by wrapping flows in general and in this case
d

DALDEI

08/07/2022, 3:13 PM
wrt flow performance. Take a look at any of the stdlib flow operators and builders. They all work like this, creating new flows and sometimes new coroutines to wrap inbound flows. That is intentionally side-stepping your performance question, turning it from a absolute to a relative statement. Doing as @ephemient does or similar should be equivilent performance to any stdlib flow operator.
e

ephemient

08/07/2022, 4:44 PM
with a caveat:
channelFlow
involves more overhead than `kotlinx.coroutines.flow.internal.flowScope`/`.scopedFlow`