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(绘制)等事件就不做介绍了。

原创粉丝点击