debounce操作符可以一定的节奏发射数据,防止生产者生产速度太快,导致下流忙不过来,典型可以用在搜索中,每次搜索框字符发生变化,就会请求数据,但是我们可以限制一定时间内只能请求一次,就可以用到debounce,该操作符会丢弃数据。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NotNull ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
Thread.sleep(1000);
emitter.onNext(2);
Thread.sleep(1000);
emitter.onNext(3);
emitter.onComplete();
}
}).debounce(4000, TimeUnit.MILLISECONDS)
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(@NotNull Disposable d) {
System.out.println("onSubscribe ");
}
@Override
public void onNext(@NotNull Integer integer) {
System.out.println("onNext " + integer);
}
@Override
public void onError(@NotNull Throwable e) {
System.out.println("onError " + e.getMessage());
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
});
输出
onSubscribe
onNext 3
onComplete
我们用debounce操作符限制4s内只能发射一次,当发射1后,sleep 1s,醒来后发射2,继续sleep 1s,这时已经消耗大概2s了,还没到4s,发射3,等到时间到达4s后将数据3发射出来。
看看源码是如何实现的
public final Observable<T> debounce(long timeout, TimeUnit unit) {
return debounce(timeout, unit, Schedulers.computation());
}
public final Observable<T> debounce(long timeout, TimeUnit unit, Scheduler scheduler) {
...
return RxJavaPlugins.onAssembly(new ObservableDebounceTimed<T>(this, timeout, unit, scheduler));
}
public final class ObservableDebounceTimed<T> extends AbstractObservableWithUpstream<T, T> {
final long timeout;
final TimeUnit unit;
final Scheduler scheduler;
public ObservableDebounceTimed(ObservableSource<T> source, long timeout, TimeUnit unit, Scheduler scheduler) {
super(source);
this.timeout = timeout;
this.unit = unit;
this.scheduler = scheduler;
}
@Override
public void subscribeActual(Observer<? super T> t) {
source.subscribe(new DebounceTimedObserver<T>(
new SerializedObserver<T>(t),
timeout, unit, scheduler.createWorker()));
}
...
}
主要还是DebounceTimedObserver对象,这里的核心还是实现worker延时执行任务,用index 标识每一个DebounceEmitter,假如这里数据身生产者生产很快,上一次的DebounceEmitter还没到执行,就需要被 d.dispose();结束掉了,那么这个数据就被丢弃了,最后一个数据,例子中就是数据3,就是延时后执行的效果。
public void onNext(T t) {
if (done) {
return;
}
long idx = index + 1;
index = idx;
Disposable d = timer;
if (d != null) {
d.dispose();
}
DebounceEmitter<T> de = new DebounceEmitter<T>(t, idx, this);
timer = de;
d = worker.schedule(de, timeout, unit);
de.setResource(d);
}
void emit(long idx, T t, DebounceEmitter<T> emitter) {
if (idx == index) {
downstream.onNext(t);
emitter.dispose();
}
}
就是说debounce操作符就是延时执行,第一条数据也是延时后发射,而不是立即发射的,该操作符还会丢弃数据。