RxJava防抖
2020-02-08 本文已影响0人
nickieeee
应用场景
快速多次点击按钮,就会提交多次事件。
一次普通的点击事件
mBtnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//这里为了更好理解,计算累加的结果
index++;
System.out.println("未添加防抖结果: "+ index);
}
});
打印结果:
2020-02-08 21:59:35.337 6487-6487/com.nick.rxjavathrottle I/System.out: 未添加防抖结果: 1
2020-02-08 21:59:35.482 6487-6487/com.nick.rxjavathrottle I/System.out: 未添加防抖结果: 2
2020-02-08 21:59:35.618 6487-6487/com.nick.rxjavathrottle I/System.out: 未添加防抖结果: 3
使用RxJava防抖
添加依赖:
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
RxView.clicks(mBtnAdd)
.throttleFirst(2, TimeUnit.SECONDS)
.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) {
index++;
System.out.println("防抖结果: "+ index);
}
});
打印结果:
2020-02-08 21:57:15.925 6189-6189/com.nick.rxjavathrottle I/System.out: 防抖结果: 1
源码分析
clicks
创建一个在指定view上可以发出的被观察者对象,这个方法返回了一个ViewClickObservable的实例化对象。
/**
* Create an observable which emits on {@code view} click events. The emitted value is
* unspecified and should only be used as notification.
* <p>
* <em>Warning:</em> The created observable keeps a strong reference to {@code view}. Unsubscribe
* to free this reference.
* <p>
* <em>Warning:</em> The created observable uses {@link View#setOnClickListener} to observe
* clicks. Only one observable can be used for a view at a time.
*/
@CheckResult @NonNull
public static Observable<Object> clicks(@NonNull View view) {
checkNotNull(view, "view == null");
return new ViewClickObservable(view);
}
ViewClickObservable类
@Override protected void subscribeActual(Observer<? super Object> observer) {
if (!checkMainThread(observer)) {
return;
}
Listener listener = new Listener(view, observer);
observer.onSubscribe(listener);
view.setOnClickListener(listener);
}
最终其实也是通过setOnClickListener来给view绑定点击事件,此处的view就是mBtnAdd。
throttleFirst
返回值为observate对象,该observate只发出源observatesource在sequential期间发出的第一项。简单来说就是比如我在2s内连续点击了3次,这里只会处理第一次的结果,后面两次会忽略掉。throttleFirst(long windowDuration, TimeUnit unit)
第一个参数为时长,第二个参数为单位。
/**
* Returns an Observable that emits only the first item emitted by the source ObservableSource during sequential
* time windows of a specified duration.
* <p>
* This differs from {@link #throttleLast} in that this only tracks passage of time whereas
* {@link #throttleLast} ticks at scheduled intervals.
* <p>
* <img width="640" height="305" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/throttleFirst.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code throttleFirst} operates by default on the {@code computation} {@link Scheduler}.</dd>
* </dl>
*
* @param windowDuration
* time to wait before emitting another item after emitting the last item
* @param unit
* the unit of time of {@code windowDuration}
* @return an Observable that performs the throttle operation
* @see <a href="http://reactivex.io/documentation/operators/sample.html">ReactiveX operators documentation: Sample</a>
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.COMPUTATION)
public final Observable<T> throttleFirst(long windowDuration, TimeUnit unit) {
return throttleFirst(windowDuration, unit, Schedulers.computation());
}
Demo:RxJavaThrottle