前言
当今天下,黄巾贼起,狼烟四顾……咳,不好意思剧本拿错了。当今天下,Rxjava异军突起,凭借其简洁明了过程可控的链式编程,和强大的操作符,深受广大开发者青睐,同时也出现很多Rx相关库,如Rxbinding、RxPermission等,还有常用的RxBus(这个不是库)。今天就来介绍一下Rxbinding的使用以及一些实用案例。
简介
RxBinding在Github上的介绍只有一句话:
RxJava binding APIs for Android UI widgets from the platform and support libraries.
用于绑定Android UI控件响应的Rxjava API。下面看个示例就了然了。目前最新版本为2.1.1,本篇示例也是基于此版本。
引入:
implementation ‘com.jakewharton.rxbinding2:rxbinding:2.1.1’
实用场景
1,按钮防抖动
业务中经常有这种问题,点击某个按钮访问网络或跳转页面等,如果每次点击都响应,用户在快速点击时会出现过于频繁访问网络或者页面多次跳转,这时候就需要做按钮防抖动。传统的实现方式是记录每次点击时的时间戳,下次点击时与上次时间比对,如果时间差小于设定的值就不响应。而使用Rxbinding的方式简单明了:
RxView.clicks(btnTest)
//1s内只发射第一个响应事件,过滤掉后面的
.throttleFirst(1, TimeUnit.SECONDS)
.subscribe(new Consumer
2,EditText监听防抖动
在做实时搜索功能时,需要监听用户输入内容实时搜索。如果用户每输入一个字符就访问一次网络,用户输入过快的情况下,会瞬间创建多个网络请求,很容易导致数据错乱,而且输入过快情况下,完全可以过滤掉前面的访问事件,只进行最后一次访问。如下:
RxTextView.textChanges(editText)
//收到监听事件600ms内没有下一个事件发来时,发送此事件
.debounce(600, TimeUnit.MILLISECONDS)
//当有多个网络请求时,以最后一个发送的请求为准,会取消掉之前执行中的请求
//常与debounce配合使用,防止数据出错
.switchMap(new Function>() {
@Override
public ObservableSource apply(CharSequence charSequence) throws Exception {
//模拟网络操作,获取数据
return Observable.just(1, 2, 3);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer() {
@Override
public void accept(Integer value) throws Exception {
System.out.println("accept:" + value);
}
});
3,表单验证
用户手机号登录界面经常有这种需求,再输入了手机号和验证码,并且手机号和验证码的长度符合要求时,登录按钮才变成可点击状态。此时使用Rxbinding结合combineLatest操作符搞定。
combineLatest操作符的作用:CombineLatest则在原始的Observable中任意一个发射了数据时发射一条数据。当原始Observables的任何一个发射了一条数据时,CombineLatest使用一个函数结合它们最近发射的数据,然后发射这个函数的返回值。
Observable
.combineLatest(
RxTextView.textChanges(etPhone)
.map(new Function() {
@Override
public String apply(CharSequence charSequence) throws Exception {
return String.valueOf(charSequence);
}
}),
RxTextView.textChanges(etPwd)
.map(new Function() {
@Override
public String apply(CharSequence charSequence) throws Exception {
return String.valueOf(charSequence);
}
}),
new BiFunction() {
@Override
public Boolean apply(String s, String s2) throws Exception {
return s.length() == 11 && s2.length() == 6;
}
})
.subscribe(new Consumer() {
@Override
public void accept(Boolean aBoolean) throws Exception {
if (aBoolean){
btnLogin.setEnabled(true);
}else {
btnLogin.setEnabled(false);
}
}
});
4,轮询
有时候用户某个动作需要触发轮询访问,操作符搞定很方便。关于concatMap
和更多变换类操作符介绍,点击这里。
//点击按钮出发轮询,不需要轮询或页面关闭时要注销掉
Disposable disposable = RxView.clicks(btnTest)
.concatMap(new Function
5,想要支持更多控件,引入对应支持库
如果想要在更多view上使用Rxbinding,引入对应的支持库即可,如:
对support-v4的支持,引入:
implementation ‘com.jakewharton.rxbinding2:rxbinding-support-v4:2.1.1’
对appcompat-v7的支持,引入:
implementation ‘com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.1.1’
对design包的支持:
implementation ‘com.jakewharton.rxbinding2:rxbinding-design:2.1.1’
对recyclerview-v7的支持,引入:
implementation ‘com.jakewharton.rxbinding2:rxbinding-recyclerview-v7:2.1.1’
对leanback-v17的支持:
implementation ‘com.jakewharton.rxbinding2:rxbinding-leanback-v17:2.1.1’
Rxbinding内容是怎么实现的呢?其实对rxjava熟悉的伙伴,看到使用方式就猜出个一二了。就是对响应事件的封装,生成Observable对象返回,然后就可以使用rxjava强大的操作符进行一系列加工处理了。我们以点击事件为例:
RxView.clicks(btnTest);
看下clicks
的实现:
@CheckResult @NonNull
public static Observable
第一句是判空,第二句是生成ViewClickObservalbe对象,看到名称应该知道这是一个自定义Observable,我们看下该对象的实现:
final class ViewClickObservable extends Observable
继承了Observable,在订阅执行的方法subscribeActual里面,设置了监听,该监听实现了OnClickListener接口。所以归根结底还是设置OnClickListener监听。其他方法也都是类似的方式来实现的。明白了原理,如果我们写了一个自定义view,完全可以写出一个相对应功能的Rxbinding出来(提升逼格的好方法)。