Rxjava(过滤类)-Debounce

仅在过了一段指定的时间还没发射数据时才发射一个数据


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,最终调用到我们的代码。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值