为什么要使用RxBinding,如下场景:
点击防抖
原始实现方式
public class FastActionGuard {
private static final long MIN_ACTION_INTERVAL_MS = 1000; // 1s
private static long sLastActionTimeMillis;
private FastActionGuard() {}
public static boolean isActionTooFast() {
long now = SystemClock.elapsedRealtime();
if (now - sLastActionTimeMillis < MIN_ACTION_INTERVAL_MS) {
return true;
} else {
sLastActionTimeMillis = now;
return false;
}
}
}
使用用RxBinding
RxView.clicks(shakeBtn)
.throttleFirst(1, TimeUnit.SECONDS)
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1() {
@Override
public void call(Void aVoid) {
//// TODO: 2017/5/4
showToast("throttleFirst 1秒内只响应第一次点击");
}
});
监听某按钮多次点击,比如双击
原始使用方式
public abstract class DoubleClick {
protected Context mContext;
/**
* 开始任务的时间。
*/
private long mStartTime;
/**
* 构造方法,初始化Context对象及开始的任务时间。
*
* @param context
*/
public DoubleClick(Context context) {
mContext = context;
mStartTime = -1;
}
/**
* 当某个动作要双击才执行时,调用此方法。
*
* @param delayTime
* 判断双击的时间。
* @param msg
* 当第一次点击时,弹出的提示信息。如果为null,则不作提示。
*/
public void doDoubleClick(int delayTime, String msg) {
if (!doInDelayTime(delayTime)) {
Toast.makeText(mContext, msg, delayTime).show();
}
}
/**
* 如果是在在指定的时间内则执行doOnDoubleClick,否则返回false。
*
* @param delayTime
* 指定的延迟时间。
* @return 当且仅当执行了doOnDoubleClick时返回true,否则返回false。
*/
protected boolean doInDelayTime(int delayTime) {
long nowTime = DateUtil.getCurTime();
if (nowTime - mStartTime <= delayTime) {
afterDoubleClick();
mStartTime = -1;
return true;
}
mStartTime = nowTime;
return false;
}
/**
* 当某个动作要双击才执行时,调用此方法。
*
* @param delayTime
* 判断双击的时间。
* @param msgResid
* 当第一次点击时,弹出的提示信息的资源ID。
*/
public void doDoubleClick(int delayTime, int msgResid) {
if (!doInDelayTime(delayTime)) {
Toast.makeText(mContext, msgResid, delayTime).show();
}
}
/**
* 在双击之后执行的事情。
*/
abstract protected void afterDoubleClick();
}
使用用RxBinding
Observable observable = RxView.clicks(doubleClickBtn).share();
observable.buffer(observable.debounce(400, TimeUnit.MILLISECONDS))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1>() {
@Override
public void call(List voids) {
if (voids.size() >= 2) {
//double click detected
showToast(" 400毫秒内进行了" + voids.size() + "点次击");
}
}
}, new Action1() {
@Override
public void call(Throwable throwable) {
倒计时
原始实现方式
public class VerifyButton extends Button{
private Context mContext;
private Handler mHandler;
private int mCount = 60;
private OnVerifyBtnClick mOnVerifyBtnClick;
public VerifyButton(Context context, AttributeSet attrs) {
super(context, attrs);
this.setText("获取验证码");
mContext = context;
mHandler = new Handler();
}
public void requestSendVerifyNumber() {
mHandler.postDelayed(countDown, 0);
if (mOnVerifyBtnClick != null){
mOnVerifyBtnClick.onClick();
}
}
/**
* The Count down of verification button
*/
private Runnable countDown = new Runnable() {
@Override
public void run() {
VerifyButton.this.setText(mCount +"s ");
VerifyButton.this.setBackgroundColor(getResources().getColor(R.color.disable_color));
VerifyButton.this.setTextColor(getResources().getColor(R.color.common_gray));
VerifyButton.this.setEnabled(false);
if(mCount > 0) {
mHandler.postDelayed(this, 1000);
} else {
resetCounter();
}
mCount -- ;
}
};
public void removeRunable(){
mHandler.removeCallbacks(countDown);
}
public void resetCounter(String... text) {
this.setEnabled(true);
if(null != text && text.length !=0 && !"".equals(text[0])){
this.setText(text[0]);
}else{
this.setText("重获验证码");
}
this.setBackgroundColor(getResources().getColor(R.color.transparent));
this.setTextColor(getResources().getColor(R.color.common_yellow));
mCount = 60;
}
public interface OnVerifyBtnClick{
void onClick();
}
public void setOnVerifyBtnClick(OnVerifyBtnClick onVerifyBtnClick) {
this.mOnVerifyBtnClick = onVerifyBtnClick;
}
}
使用用RxBindding
timeObservable = RxView.clicks(timeBtn)
.throttleFirst(1, TimeUnit.SECONDS)
.subscribeOn(AndroidSchedulers.mainThread())
.doOnNext(new Action1() {
@Override
public void call(Void aVoid) {
RxView.enabled(timeBtn).call(false);
}
});
timeObservable.subscribe(new Action1() {
@Override
public void call(Void aVoid) {
Observable.interval(0, 1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
.take(SECOND + 1)
.subscribe(new Observer() {
@Override
public void onCompleted() {
RxTextView.text(timeBtn).call("点击倒计时");
RxView.enabled(timeBtn).call(true);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Long aLong) {
long curTime = SECOND - aLong;
RxTextView.text(timeBtn).call("倒计时 " + curTime + "s");
}
});
}
});
文字监听,view状态监听,登录:
原始实现方式
//根据输入以及协议勾选框状态判断,是否需要高亮登录按钮
usernameEt.addTextChangedListener(....);
pwdEt.addTextChangedListener(....;
protocolCb.setOnCheckedChangeListener(....);
使用用RxBinding
Observable usernameOb = RxTextView.textChanges(usernameEt);
Observable pwdOb = RxTextView.textChanges(pwdEt);
Observable protocolOb = RxCompoundButton.checkedChanges(protocolCb);
Observable.combineLatest(usernameOb, pwdOb, protocolOb, new Func3() {
@Override
public Boolean call(CharSequence username, CharSequence pwd, Boolean isChecked) {
return !TextUtils.isEmpty(username) && !TextUtils.isEmpty(pwd) && isChecked;
}
}).subscribe(new Action1() {
@Override
public void call(Boolean aBoolean) {
RxView.enabled(highLightkBtn).call(aBoolean);
}
});
搜索
原始实现方式
//不断监听当前输入框的文字变化,然后进行搜索,还需要自己判断用户是否输入完毕
searchEt(....);
使用用RxBinding
RxTextView.textChanges(searchEt)
.debounce(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.map(new Func1() {
@Override
public String call(CharSequence charSequence) {
String searchKey = charSequence.toString();
if (TextUtils.isEmpty(searchKey)) {
showToast("搜索关键字不能为null");
}
else {
showToast("0.5秒内没有操作,关键字:" + searchKey);
}
return searchKey;
}
})
.observeOn(Schedulers.io())
.map(new Func1>() {
@Override
public List call(String searchKey) {
return search(searchKey);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1>() {
@Override
public void call(List strings) {
}
});
权限管理
原始实现方式
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
}else{
//
}
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
}
}
使用用RxBinding
final RxPermissions rxPermissions = new RxPermissions(this);
RxView.clicks(rxPerimissionsBtn).
throttleFirst(1, TimeUnit.SECONDS)
.subscribeOn(AndroidSchedulers.mainThread())
.compose(rxPermissions.ensure(Manifest.permission.CAMERA))
.subscribe(new Action1() {
@Override
public void call(Boolean granted) {
if (granted) {
showToast("允许camera权限");
}
else {
showToast("拒绝camera权限");
}
}
});
本文只写了我们常用的一些场景,后续继续补充
给我一个拒绝rxBinding的理由?
Demo:https://github.com/zhujian1989/mf