Jake Wharton的RxBinding
RxBinding系列之RxView(一)
RxBinding可将Android中各类UI控件的动作事件转换为RxJava中的数据流。也就是说可以使用RxBinding以RxJava的形式来处理UI事件。本篇主要讲解其中RxView的相关View事件如何绑定。
RxBinding中主要包含RxView、RxTextView、RxAdapterView、RxCompoundButton等等。
Platform bindings:
implementation 'com.jakewharton.rxbinding3:rxbinding:3.0.0-alpha2'
AndroidX library bindings:
implementation 'com.jakewharton.rxbinding3:rxbinding-core:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-appcompat:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-drawerlayout:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-leanback:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-recyclerview:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-slidingpanelayout:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-swiperefreshlayout:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-viewpager:3.0.0-alpha2'
Google 'material' library bindings:
implementation 'com.jakewharton.rxbinding3:rxbinding-material:3.0.0-alpha2'
click点击事件
clicks
throttleFirst(long windowDuration, TimeUnit unit),设置一定时间内只响应首次(throttleFirst)或者末次(throttleLast)的点击事件。windowDuration为防抖时间,unit为时间单位。调用这个方法便可防止短时间内对View的重复点击,本例中设置的防抖时间为 1s。
RxView.clicks(mLoginButton)
//1秒钟之内只取一个点击事件,防抖操作
.throttleFirst(1, TimeUnit.SECONDS)
.subscribe(new Consumer<Unit>() {
@Override
public void accept(Unit unit) throws Exception {
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
}
});
longClicks
RxView.longClicks(View view),内部封装了View.OnLongClickListener长按监听,原理同上。
RxView.longClicks(mLoginButton)
.subscribe(new Consumer<Unit>() {
@Override
public void accept(Unit unit) throws Exception {
Log.i(TAG, "accept: longClicks-test");
}
});
RxTextView
/**
* accept: rxbindg_test before0-start-0-textxx
* accept: rxbindg_test before12-start-12-textxx
*/
RxTextView.textChangeEvents(mPswEditText)
.subscribe(new Consumer<TextViewTextChangeEvent>() {
@Override
public void accept(TextViewTextChangeEvent textViewTextChangeEvent) throws Exception {
Log.i(TAG, "accept: rxbindg_test before"+textViewTextChangeEvent.getStart()
+"-start-"+textViewTextChangeEvent.getStart()
+"-text"+textViewTextChangeEvent.getText()+"count"+textViewTextChangeEvent.getCount());
}
});
RxTextView结合combineLatest操作符:
应用场景:登录时满足所有条件下,登录按钮才可以点击
说明:监听多个被观察者是否变化,在一个地方进行统一验证,如果验证成功,那么允许用户进行下一步的操作,否则提示用户输入不正确,有任意一个被观察者发生改变时,会去取 其它 Observable 最近一次发射的数据,回调到函数当中。combineLatest就被触发连接几个被观察者进行校验。
比如以下的两个被观察者,启动APP并没有再用户名和密码输入框中输入数据,但是此时这两个控件已被监听,相当于所有的Observable都至少发射过一个数据项,监听结果为空直接触发apply事件,输入用户名时被观察者nameObservable发生变化,也直接触发apply事件。
private void initFilter() {
InitialValueObservable<CharSequence> nameObservable = RxTextView.textChanges(userNameEditText);
InitialValueObservable<CharSequence> pwdObservable = RxTextView.textChanges(userPwdEditText);
InitialValueObservable<CharSequence> checkBoxObservable = RxTextView.textChanges(userPwdEditText);
nameObservable.subscribe(new Consumer<CharSequence>() {
@Override
public void accept(CharSequence charSequence) throws Exception {
String txt = charSequence.toString();
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
}
});
Observable.combineLatest(nameObservable, pwdObservable, new BiFunction<CharSequence, CharSequence, Boolean>() {
@Override
public Boolean apply(CharSequence charSequence, CharSequence charSequence2) throws Exception {
boolean isEnnable = !TextUtils.isEmpty(userNameEditText.getText().toString()) && !TextUtils.isEmpty(userPwdEditText.getText().toString());
Log.i(TAG, "apply: " + isEnnable);
return isEnnable;
}
}).subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean aBoolean) throws Exception {
Log.i(TAG, "accept: " + aBoolean);
if (aBoolean) {
loginButton.setBackgroundColor(0xffFF0000);
loginButton.setClickable(true);
} else {
loginButton.setBackgroundColor(0xff00FF00);
loginButton.setClickable(false);
}
}
});
Observable.combineLatest(mobileObservable, passwordObservable, new BiFunction<CharSequence, CharSequence, Object>() {
@Override
public Object apply(CharSequence mobile, CharSequence password) throws Exception {
Log.d(TAG,"合并事件订阅 "+mobile+" "+password);
//手机号、短信验证码、勾选框 都符合条件时,才允许点击登录
if(!TextUtils.isEmpty(mobile) && !TextUtils.isEmpty(password)){
loginButton.setClickable(true);
loginButton.setBackgroundResource(R.drawable.basic_login_bg02);
}else{
loginButton.setClickable(false);
loginButton.setBackgroundResource(R.drawable.basic_login_bg01);
}
return new Object();
}
}).subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(activityContext, Lifecycle.Event.ON_DESTROY)))
.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {}
});