RxBinding详解之clicks事件源码解析
来源:互联网 发布:淘宝买电玩人马皮肤 编辑:程序博客网 时间:2024/05/27 12:21
RxBinding概念说明
RxBinding 是 Jake Wharton 的一个开源库,它提供了一套在 Android 平台上的基于 RxJava 的 Binding API。所谓 Binding,就是类似设置 OnClickListener 、设置 TextWatcher 这样的注册绑定对象的 API。
Android 开发中一个比较典型的例子是点击监听器 OnClickListener 。对设置 OnClickListener 来说, View 是被观察者, OnClickListener 是观察者,二者通过 setOnClickListener() 方法达成订阅关系。订阅之后用户点击按钮的瞬间,Android Framework 就会将点击事件发送给已经注册的 OnClickListener 。采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。
通过 setOnClickListener() 方法,Button 持有 OnClickListener 的引用;当用户点击时,Button 自动调用 OnClickListener 的 onClick() 方法。概念抽象出来就是(Button -> 被观察者、OnClickListener -> 观察者、setOnClickListener() -> 订阅,手指点击onClick() -> 事件)。
若想了解RxJava整个事件流程请参考 RxJava源码深度解析 文章
实例演示
在build.gradle文件中添加依赖
compile 'io.reactivex:rxandroid:1.2.1'compile 'io.reactivex:rxjava:1.2.1'compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'
添加点击事件
RxView.clicks(mBtn1).throttleFirst(1, TimeUnit.SECONDS).subscribe(new Action1<Void>() { @Override public void call(Void aVoid) { Log.d("rxview_clicks", "btn1"); } });
给mBtn1按钮设置点击事件,设置点击间隔时间为1秒,只有超过这个时间点击回调的call方法才会执行。
下面是手指连续点击打印的结果(每隔1秒点击才会回调call一次)
11-10 09:57:35.508 4452-4452/com.cn.liuyz.javademo D/rxview_clicks: btn111-10 09:57:36.556 4452-4452/com.cn.liuyz.javademo D/rxview_clicks: btn111-10 09:57:37.779 4452-4452/com.cn.liuyz.javademo D/rxview_clicks: btn1
RxBinding的clicks源码解析
clicks(View v)方法
给view注册点击事件
public static Observable<Void> clicks(@NonNull View view) { //检查view是否为空,空直接报异常 checkNotNull(view, "view == null"); return Observable.create(new ViewClickOnSubscribe(view)); }
public static <T> Observable<T> create(OnSubscribe<T> f) { //f:ViewClickOnSubscribe对象 //RxJavaHooks.onCreate(f)传进入什么返回什么 return new Observable<T>(RxJavaHooks.onCreate(f)); }
protected Observable(OnSubscribe<T> f) { //把ViewClickOnSubscribe对象赋值给onSubscribe,这里起别名为onSubscribe1,因为后边会用到很多 this.onSubscribe = f; }
ViewClickOnSubscribe类
ViewClickOnSubscribe(View view) { //把我们界面的view传进来 this.view = view; }
clicks方法是在内部创建了ViewClickOnSubscribe对象和Observable对象,在Observable的构造中把ViewClickOnSubscribe对象赋值给onSubscribe,起别名为onSubscribe1。
throttleFirst(long,TimeUnit)方法
throttleFirst() 是设置点击间隔时间,用于去抖动,也就是消除手抖导致的快速连环点击
public final Observable<T> throttleFirst(long windowDuration, TimeUnit unit) { return throttleFirst(windowDuration, unit, Schedulers.computation()); }
public final Observable<T> throttleFirst(long skipDuration, TimeUnit unit, Scheduler scheduler) { return lift(new OperatorThrottleFirst<T>(skipDuration, unit, scheduler)); }
OperatorThrottleFirst对象
public OperatorThrottleFirst(long windowDuration, TimeUnit unit, Scheduler scheduler) { this.timeInMilliseconds = unit.toMillis(windowDuration); this.scheduler = scheduler; }
- timeInMilliseconds:等待时间
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) { return create(new OnSubscribeLift<T, R>(onSubscribe, operator)); }
- onSubscribe:就是上边的别名onSubscribe1对象,即ViewClickOnSubscribe
- operator:OperatorThrottleFirst对象
OnSubscribeLift对象
public OnSubscribeLift(OnSubscribe<T> parent, Operator<? extends R, ? super T> operator) { this.parent = parent; this.operator = operator; }
- parent:就是别为onSubscribe1的对象,即ViewClickOnSubscribe
- operator:是OperatorThrottleFirst对象
public static <T> Observable<T> create(OnSubscribe<T> f) { return new Observable<T>(RxJavaHooks.onCreate(f)); }
protected Observable(OnSubscribe<T> f) { //把OnSubscribeLift对象赋值给onSubscribe this.onSubscribe = f; }
throttleFirst方法是在内部内部创建了OperatorThrottleFirst对象,又把OperatorThrottleFirst对象传给了OnSubscribeLift对象,又把OnSubscribeLift对象传给了Observable对象,又把OnSubscribeLift对象赋值给onSubscribe,这里起别名为onSubscribe2。
subscribe(Action1)订阅
使View和ViewClickOnSubscribe产生订阅关系
public final Subscription subscribe(final Action1<? super T> onNext) { //判断Action1是否为空 if (onNext == null) { throw new IllegalArgumentException("onNext can not be null"); } Action1<Throwable> onError = InternalObservableUtils.ERROR_NOT_IMPLEMENTED; Action0 onCompleted = Actions.empty(); return subscribe(new ActionSubscriber<T>(onNext, onError, onCompleted)); }
创建ActionSubscriber对象
public ActionSubscriber(Action1<? super T> onNext, Action1<Throwable> onError, Action0 onCompleted) { this.onNext = onNext; this.onError = onError; this.onCompleted = onCompleted; }
- onNext:我们传入的Action1对象
public final Subscription subscribe(Subscriber<? super T> subscriber) { return Observable.subscribe(subscriber, this); }
- subscriber:是ActionSubscriber对象
- this:是通过调用throttleFirst(…)方法返回的Observable对象
static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) { if (subscriber == null) { throw new IllegalArgumentException("subscriber can not be null"); } if (observable.onSubscribe == null) { throw new IllegalStateException("onSubscribe function can not be null."); } subscriber.onStart(); //subscriber是ActionSubscriber对象,所以会进入 //转换成安全的SafeSubscriber对象 if (!(subscriber instanceof SafeSubscriber)) { subscriber = new SafeSubscriber<T>(subscriber); } try { //onObservableStart传进什么返回什么 RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber); return RxJavaHooks.onObservableReturn(subscriber); } catch (Throwable e) { .....省略..... } }
- observable.onSubscribe:是别名onSubscribe2对象,即OnSubscribeLift对象
这里就是调用OnSubscribeLift的call方法并把ActionSubscriber对象传进去
OnSubscribeLift的call方法
public void call(Subscriber<? super R> o) { try { Subscriber<? super T> st = RxJavaHooks.onObservableLift(operator).call(o); try { st.onStart(); parent.call(st); } catch (Throwable e) { .....省略..... } } catch (Throwable e) { .....省略..... } }
- o:是ActionSubscriber对象
- operator:是OperatorThrottleFirst对象
- parent:就是别为onSubscribe1的对象,即ViewClickOnSubscribe
- st:就是通过调用call(o)返回的Subscriber对象
这里是调用OperatorThrottleFirst的call方法并把OperatorThrottleFirst对象传进去,然后再调用ViewClickOnSubscribe的call方法并把st传进去。
现在先看下OperatorThrottleFirst的call方法,稍等再看ViewClickOnSubscribe的call方法
OperatorThrottleFirst的call方法
public Subscriber<? super T> call(final Subscriber<? super T> subscriber) { return new Subscriber<T>(subscriber) { .....省略..... }; }
- subscriber:是ActionSubscriber对象
这里就是给OnSubscribeLift类中call方法内OperatorThrottleFirst.call(o)方法返回一个Subscriber对象。
紧接着看ViewClickOnSubscribe的call方法
public void call(final Subscriber<? super Void> subscriber) { checkUiThread();//检查是否在UI线程 View.OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View v) { if (!subscriber.isUnsubscribed()) { //调用onNext方法 subscriber.onNext(null); } } }; //设置view的点击监听事件 view.setOnClickListener(listener); .....省略..... }
- subscriber:在OperatorThrottleFirst类中创建的Subscriber对象
- view:我们传进来的View
这里首先检查程序运行是否在主线程,然后注册View的点击事件,当点击onClick()事件发生时回调Subscriber的onNext方法
这里回调的onNext方法就是在OperatorThrottleFirst类中创建的Subscriber对象内的onNext方法
public Subscriber<? super T> call(final Subscriber<? super T> subscriber) { return new Subscriber<T>(subscriber) {//上面就是调用此对象的onNext方法 private long lastOnNext = -1; .....省略..... @Override public void onNext(T v) { long now = scheduler.now();//获取当前时间 if (lastOnNext == -1 || now - lastOnNext >= timeInMilliseconds) { lastOnNext = now; subscriber.onNext(v); } } .....省略..... }; }
- subscriber:是ActionSubscriber对象
- timeInMilliseconds:我们传入的时间
- v:null
这里就是调用Subscriber的onNext方法,首次点击lastOnNext为-1进入,再次点击则开始判断是否超过了我们传入的时间,超过则再会进去,以此来达到View的多长时间可点击一次。
ActionSubscriber的onNext(v)方法
public void onNext(T t) { onNext.call(t); }
- onNext:我们自己创建的Action1对象
这里就回调到我们自己创建的Action1的call方法了。
其他事件用法
只响应首次事件
private Subscription subscription; private void initClick() { Action1 action1 = new Action1() { @Override public void call(Object o) { Log.d("rxview_clicks", "btn1"); subscription.unsubscribe();//取消订阅 } }; subscription = RxView.clicks(mBtn1).throttleFirst(1, TimeUnit.SECONDS).subscribe(action1); }
longClicks长按事件
RxView.longClicks(mBtn1) .throttleFirst(5, TimeUnit.SECONDS) .subscribe(new Action1<Void>() { @Override public void call(Void aVoid) { Log.d("rxview_longClicks", "btn1"); } });
还有一些layoutChanges(布局变化)、scrollChange(滑动)、draws(绘制)等事件就不做介绍了。
- RxBinding详解之clicks事件源码解析
- 初涉Rx套餐 之RxBinding(让你的事件流程更清晰)
- Android之Button控件多次点击问题及RxBinding事件流
- Vue-lazyload原理详解之源码解析
- RxBinding系列之RxView(一)
- RxBinding系列之RxTextView(二)
- RxBinding系列之RxCompoundButton(三)
- RxBinding系列之RxAdapterView(四)
- 事件总线源码解析
- Android源码解析之四:View事件分发机制
- jquery源码解析之ready与load事件
- Android源码基础解析之截屏事件流程
- Android源码基础解析之HOME事件流程
- Android源码基础解析之电源开关机按键事件流程
- 使用RxBinding响应控件的异步事件
- 使用RxBinding响应控件的异步事件
- 使用RxBinding响应控件的异步事件
- 详解 QT 源码之 Qt 事件机制原理
- C++中的string类的用法总结
- (二)JAVA入门--继承
- C#进程 线程学习笔记1
- 03 C++中复合、委托和继承的基本用法(学自Boolean)
- 界面初建
- RxBinding详解之clicks事件源码解析
- B-number(数位dp)
- 解码器的bug笔记
- 集合的3种遍历形式(一般for循环、增强型for循环、迭代器)
- Tomcat基础实验一
- 小程序学习心得之数据绑定技巧
- 一次Windows上OracleMTSRecoveryService无法启动问题
- POJ 1251 Jungle Roads (prim)
- Maven的使用