為什么要使用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<Void>() {
@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<Void> observable = RxView.clicks(doubleClickBtn).share();
observable.buffer(observable.debounce(400, TimeUnit.MILLISECONDS))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<Void>>() {
@Override
public void call(List<Void> voids) {
if (voids.size() >= 2) {
//double click detected
showToast(" 400毫秒內進行了" + voids.size() + "點次擊");
}
}
}, new Action1<Throwable>() {
@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<Void>() {
@Override
public void call(Void aVoid) {
RxView.enabled(timeBtn).call(false);
}
});
timeObservable.subscribe(new Action1<Void>() {
@Override
public void call(Void aVoid) {
Observable.interval(0, 1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
.take(SECOND + 1)
.subscribe(new Observer<Long>() {
@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<CharSequence> usernameOb = RxTextView.textChanges(usernameEt);
Observable<CharSequence> pwdOb = RxTextView.textChanges(pwdEt);
Observable<Boolean> protocolOb = RxCompoundButton.checkedChanges(protocolCb);
Observable.combineLatest(usernameOb, pwdOb, protocolOb, new Func3<CharSequence, CharSequence, Boolean, Boolean>() {
@Override
public Boolean call(CharSequence username, CharSequence pwd, Boolean isChecked) {
return !TextUtils.isEmpty(username) && !TextUtils.isEmpty(pwd) && isChecked;
}
}).subscribe(new Action1<Boolean>() {
@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<CharSequence, String>() {
@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<String, List<String>>() {
@Override
public List<String> call(String searchKey) {
return search(searchKey);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<String>>() {
@Override
public void call(List<String> 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<Boolean>() {
@Override
public void call(Boolean granted) {
if (granted) {
showToast("允許camera權限");
}
else {
showToast("拒絕camera權限");
}
}
});
本文只寫了我們常用的一些場景,后續繼續補充
給我一個拒絕rxBinding的理由?
Demo:https://github.com/zhujian1989/mf
4.png