仅在过了一段指定的时间还没发射数据时才发射一个数据
demo
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
try {
int i = 10;
while (i > 0) {
subscriber.onNext(i);
Thread.sleep(1000);
subscriber.onNext(i + 100);
Thread.sleep(600);
subscriber.onNext(i + 1000);
Thread.sleep(800);
i--;
}
System.out.println("onCompleted");
subscriber.onCompleted();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
})
.debounce(700, TimeUnit.MILLISECONDS)
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println(integer);
}
});
输出
10
1010
9
1009
8
1008
7
1007
6
1006
5
1005
4
1004
3
1003
2
1002
1
1001
onCompleted
可以看到,中间一个onNext被忽略掉了,因为发射数据的时间间隔小于800ms,输出的是当前时间间隔内最后发出的值
看下debounce的源码
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 lift(new OperatorDebounceWithTime<T>(timeout, unit, scheduler));
}
看下OperatorDebounceWithTime
public final class OperatorDebounceWithTime<T> implements Operator<T, T> {
final long timeout;
final TimeUnit unit;
final Scheduler scheduler;
/**
* @param timeout
* How long each event has to be the 'last event' before it gets published.
* @param unit
* The unit of time for the specified timeout.
* @param scheduler
* The {@link Scheduler} to use internally to manage the timers which handle timeout for each event.
*
*/
public OperatorDebounceWithTime(long timeout, TimeUnit unit, Scheduler scheduler) {
this.timeout = timeout;
this.unit = unit;
this.scheduler = scheduler;
}
@Override
public Subscriber<? super T> call(final Subscriber<? super T> child) {
final Worker worker = scheduler.createWorker();
final SerializedSubscriber<T> s = new SerializedSubscriber<T>(child);
final SerialSubscription serial = new SerialSubscription();
s.add(worker);
s.add(serial);
return new Subscriber<T>(child) {
final DebounceState<T> state = new DebounceState<T>();
final Subscriber<?> self = this;
@Override
public void onStart() {
request(Long.MAX_VALUE);
}
@Override
public void onNext(final T t) {
final int index = state.next(t);
serial.set(worker.schedule(new Action0() {
@Override
public void call() {
state.emit(index, s, self);
}
}, timeout, unit));
}
@Override
public void onError(Throwable e) {
s.onError(e);
unsubscribe();
state.clear();
}
@Override
public void onCompleted() {
state.emitAndComplete(s, this);
}
};
}
/**
* Tracks the last value to be emitted and manages completion.
* @param <T> the value type
*/
static final class DebounceState<T> {
/** Guarded by this. */
int index;
/** Guarded by this. */
T value;
/** Guarded by this. */
boolean hasValue;
/** Guarded by this. */
boolean terminate;
/** Guarded by this. */
boolean emitting;
public synchronized int next(T value) { // NOPMD
this.value = value;
this.hasValue = true;
return ++index;
}
public void emit(int index, Subscriber<T> onNextAndComplete, Subscriber<?> onError) {
T localValue;
synchronized (this) {
if (emitting || !hasValue || index != this.index) {
return;
}
localValue = value;
value = null;
hasValue = false;
emitting = true;
}
try {
onNextAndComplete.onNext(localValue);
} catch (Throwable e) {
Exceptions.throwOrReport(e, onError, localValue);
return;
}
// Check if a termination was requested in the meantime.
synchronized (this) {
if (!terminate) {
emitting = false;
return;
}
}
onNextAndComplete.onCompleted();
}
public void emitAndComplete(Subscriber<T> onNextAndComplete, Subscriber<?> onError) {
T localValue;
boolean localHasValue;
synchronized (this) {
if (emitting) {
terminate = true;
return;
}
localValue = value;
localHasValue = hasValue;
value = null;
hasValue = false;
emitting = true;
}
if (localHasValue) {
try {
onNextAndComplete.onNext(localValue);
} catch (Throwable e) {
Exceptions.throwOrReport(e, onError, localValue);
return;
}
}
onNextAndComplete.onCompleted();
}
public synchronized void clear() { // NOPMD
++index;
value = null;
hasValue = false;
}
}
}
同样这里主要看call中新建订阅者的onNext方法
public void onNext(final T t) {
final int index = state.next(t);
serial.set(worker.schedule(new Action0() {
@Override
public void call() {
state.emit(index, s, self);
}
}, timeout, unit));
}
state是DebounceState
public synchronized int next(T value) { // NOPMD
this.value = value;
this.hasValue = true;
return ++index;
}
这里把当前发射的值保存到value,hasValue设置为true,++index并返回当前的index值
接下来调用
serial.set(worker.schedule(new Action0() {
@Override
public void call() {
state.emit(index, s, self);
}
}, timeout, unit));
这里超时过后会调用call
调用state的emit
public void emit(int index, Subscriber<T> onNextAndComplete, Subscriber<?> onError) {
T localValue;
synchronized (this) {
if (emitting || !hasValue || index != this.index) {
return;
}
localValue = value;
value = null;
hasValue = false;
emitting = true;
}
try {
onNextAndComplete.onNext(localValue);
} catch (Throwable e) {
Exceptions.throwOrReport(e, onError, localValue);
return;
}
// Check if a termination was requested in the meantime.
synchronized (this) {
if (!terminate) {
emitting = false;
return;
}
}
onNextAndComplete.onCompleted();
}
这里如果emitting=true表示当前正在发射,则丢弃直接返回
或者hasValue=false,表示没有值,也返回
或者index!=this.index,表示当它超时回来之前,又发射了其他的值,导致State的index有变化,也返回,丢弃当次值
如果上述条件都不满足,调用
onNextAndComplete.onNext(localValue);
onNextAndComplete是SerializedSubscriber
public void onNext(T t) {
s.onNext(t);
}
s是SerializedObserver
public void onNext(T t) {
if (terminated) {
return;
}
synchronized (this) {
if (terminated) {
return;
}
if (emitting) {
FastList list = queue;
if (list == null) {
list = new FastList();
queue = list;
}
list.add(NotificationLite.next(t));
return;
}
emitting = true;
}
try {
actual.onNext(t);
} catch (Throwable e) {
terminated = true;
Exceptions.throwOrReport(e, actual, t);
return;
}
for (;;) {
FastList list;
synchronized (this) {
list = queue;
if (list == null) {
emitting = false;
return;
}
queue = null;
}
for (Object o : list.array) {
if (o == null) {
break;
}
try {
if (NotificationLite.accept(actual, o)) {
terminated = true;
return;
}
} catch (Throwable e) {
terminated = true;
Exceptions.throwIfFatal(e);
actual.onError(OnErrorThrowable.addValueAsLastCause(e, t));
return;
}
}
}
}
调用
actual.onNext(t);
actual是SafeSubscriber,最终调用到我们的代码。