kotlinx.coroutines
kotlinx.coroutines copied to clipboard
Add sample operator to Flow, which can sample a Flow with the emissions of another Flow
The aim of this PR is to bring the ability to sample
a flow
with the emissions from another flow. I've a extension methods to Flow
:
Flow<T>.sampleBy(sampler:ReceiveChannel<R>)
which samples a flow whenever the receive channel emits.
Notes:
- The current sample has been refactored to use the
sampleBy
method with a simpleflow
of an interval. - All the current test cases for
sample(period)
have been added for both the operators (in a new file calledSampleByTest
). - The operator can still be called
sample
, but I thinksampleBy
is more readable/understandable.
Example of sampleBy
with another Flow:
flow {
repeat(10) {
emit(it)
delay(50)
}
}.sampleBy(flow {
repeat(10) {
delay(100)
emit(it)
}
})
produces 0, 2, 4, 6, 8
.
Each ReceiveChannel
can be converted to a Flow
, why overload this operator for both types?
Is Flow<T>.sampleBy(sampler: Flow<R>): Flow<T>
enough?
@fvasco That makes sense. I removed the channel operator with its unit tests since they can easily be converted to flows.
Can you, please, clarify what is the use-case for sampleBy
? In what kind of circumstance and applications it might be needed?
sampleBy
operator is the more generalized version of the sample operator, which is not bound to time. The user of this operator can specify any kind of flow emission for the sampling to work. Its application is synchronizing (and restrict) events from an observable source, with another.
RxJava implementation of sample
One simple use case for this operator would be the Refresh Button in Gmail when there's new mails available:
-
A flow which emits data whenever the data is updated
-
A Refresh button that exposes a flow for its click events.
-
We want our UI to be updated according to the latest received data, whenever the user presses the refresh button.
These two flows cannot be:
-
combinedLatest
with each other, since If the user has clicked on the refresh button, on every emission of data afterwards, the page would suddenly get updated. -
zip
with each other, aside from the previous problem, if the user clicks on the refresh button multiple times, the UI would not get updated if the data is not received in the mean time..
I renamed the operator to sample
, since sampleBy
was kind of a new name (it made no sense, since If we are doing that, other operators such as flatMap
should become flatMapBy
).
Also, I've updated the code to use the new flowScope
and renamed the the unit test functions to match the original ones.
@elizarov does this PR need further improvements? I'm asking since it becomes a stale/conflicting branch after a few days.
We have not reached consensus yet on whether we should add sampleBy
to the core library in the first place, so please hold on.
@elizarov Since this PR is still open (which is appreciated, after 4 years 😅), I've updated it with master so we can decide on merging or closing it. Please do let me know if it needs anything else to make it reach the decision.
Just to reiterate this PR's purpose, it generalizes the sample
operator to accept a flow
as its input (instead of just a time), so users can sample their flows with other flows (e.g. emit my last value when the other emits).
Thanks.