RxJava has two way of dealing with producers being more active than subscribers:
- Various flow-control mechanisms such as sampling and batching are implemented via built-in operators
- Subscribers can propagate theri demand and request only as many tiems as they can process by using a feedback channel known as backpressure.
Flow Control
Taking Periodic Samples and Throttling
sample() has a more advanced variant taking Observable as an argument rather than a fixed period.This second Observable (known as sampler) basically dictates when to take a sample from the upstream source:every time sampler emits any value,a new sample is taken (if any new value appeared since the last sample)
Buffering Events to a List
buffer(count)
buffer(count, skip)
buffer(boundary)
buffer(bufferOpenings, bufferClosingSelector)
For example
Observable<Duration> insideBusinessHours = Observable
.interval(1,SECONDS)
.filter(x -> isBusinessHour())
.map(x -> Duration.ofMillis(100));
Observable<Duration> outsideBusinessHours = Observable
.interval(5,SECONDS)
.filter(x -> !isBusinessHour())
.map(x -> Duration.ofMillis(200));
Observable<Duration> openings = Observable.merge(
insideBusinessHours,outsideBusinessHours);
Observable<List<TeleData>> samples = upstream
.buffer(
openings,
duration -> empty()
.delay(duration.toMillis(),MILLISECONDS));
Moving window
Because buffer() requires creating an intermediate List before the current buffer is closed and passed downstream,it might unnecessarily put pressure on garbage
Observable<KeyEvent> keyEvents = //...
//buffer
Observable<Integer> eventPerSecond = keyEvents
.buffer(1,SECONDS)
.map(List::size);
vs
//window
Obsevable<Observable<KeyEvent>> windows = keyEvents.window(1,SECONDS);
Observable<Integer> eventPerSecond = windows
.flatMap(eventInSecond -> eventInSecond.count());
Skipping Stale Events by Using debounce()
Returns an Observable that mirrors the source Observable, except that it drops items emitted by the source Observable that are followed by newer items before a timeout value expires. The timer resets on each emission.
Note: If items keep being emitted by the source Observable faster than the timeout then no items will be emitted by the resulting Observable.
debounce(long,TimeUnit):
debounce(Func1)
Observable<Long> timedDebounce(Observable<Long> upsteam) {
Observable<Long> onTimeout = upstream
.take(1)
.concatWith(defer(() -> timedDebounce(upstream)));
return upstream
.debounce(100,MILLISECONDS)
.timeout(1,SECONDS,onTimeout);
}
最后,安利一款自己写的基于MVP的Android开发框架
https://github.com/sxenon/Pure
欢迎大家拍砖,如果觉得好,麻烦多多star