前言
自從用上RxJava後徹底迷上Rx系列響應式程式設計,從本篇開始一起來學習一下Rx套餐之一的RxBinding。RxBinding是什麼?它是一組開源庫,來自大神Jake Wharton之手,可將Android中各類UI控制元件的動作事件轉換為RxJava中的資料流。也就是說使用RxBinding,我們就可以以RxJava的形式來處理UI事件。本篇主要講解其中RxView的相關View事件如何繫結。
RxBinding中主要包含RxView、RxTextView、RxAdapterView、RxCompoundButton等等。由於全寫一起篇幅太長,我就一篇講解一種了。本系列主要講解以上常用的4種,詳細內容可飛機到:
Jake Wharton的RxBinding
依賴
本系列圍繞我自己編寫的RxBindingDemo來進行講解,專案中主要使用ButterKnife做View注入,RxBinding做事件繫結。RxBindingDemo程式碼在文末有給地址。
注意:RxBinding包中包含RxJava的內容,所以就無需再新增RxJava的依賴了。
dependencies {
......
compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}複製程式碼
BaseActivity
相信學習過RxJava的碼友一定記得,使用RxJava例項化的Disposable需在不用時及時銷燬。
由於每個Activity中都寫一套add與clear的方法會造成程式碼冗餘,所以我將它們封裝到BaseActivity中方便統一對Disposable進行管理,以及ButterKnife的統一繫結與解綁。
獻上程式碼:
public abstract class BaseActivity extends AppCompatActivity {
public CompositeDisposable mCompositeDisposable;
private Unbinder mUnbinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
mUnbinder = ButterKnife.bind(this);
mCompositeDisposable = new CompositeDisposable();
onViewCreated(savedInstanceState);
}
/**
* 新增訂閱
*/
public void addDisposable(Disposable mDisposable) {
if (mCompositeDisposable == null) {
mCompositeDisposable = new CompositeDisposable();
}
mCompositeDisposable.add(mDisposable);
}
/**
* 取消所有訂閱
*/
public void clearDisposable() {
if (mCompositeDisposable != null) {
mCompositeDisposable.clear();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
clearDisposable();
mUnbinder.unbind();
}
protected abstract int getLayoutId();
protected abstract void onViewCreated(Bundle savedInstanceState);
}複製程式碼
click點選事件
clicks
RxView.clicks(View view)
,通過原始碼可發現其內部封裝了View.OnClickListener點選監聽,呼叫clicks方法返回一個Observable物件,每當點選這個View的時候,該Observable物件就會發射一個事件,隨即呼叫onNext()方法,Observable對應的觀察者就可以通過onNext()回撥響應此次點選事件。使用RxBinding還可做到點選防抖的效果。來看程式碼:
addDisposable(RxView.clicks(btnClick)
.throttleFirst(2, TimeUnit.SECONDS)
.subscribe(o -> {
Log.e("rx_binding_test", "clicks:點選了按鈕:兩秒內防抖");
}));複製程式碼
throttleFirst(long windowDuration, TimeUnit unit)
,設定一定時間內只響應首次(throttleFirst)或者末次(throttleLast)的點選事件。windowDuration為防抖時間,unit為時間單位。呼叫這個方法便可防止短時間內對View的重複點選,本例中設定的防抖時間為2s。從程式碼看來是不是方便又簡潔呢,以往實現防抖還得新增各種標記,忒麻煩。
longClicks
RxView.longClicks(View view)
,內部封裝了View.OnLongClickListener長按監聽,原理同上。
addDisposable(RxView.longClicks(btnClick)
.subscribe(o -> {
Log.e("rx_binding_test", "longClicks:長點選了按鈕");
}));複製程式碼
draw繪製事件
RxView.draws(View view)
,內部封裝了OnDrawListener繪製監聽。
//點選btnDraw呼叫viewCanvas的繪製
addDisposable(RxView.clicks(btnDraw)
.throttleFirst(2, TimeUnit.SECONDS)
.subscribe(o -> {
//此處可模擬讓viewCanvas繪製
//viewCanvas.getViewTreeObserver().dispatchOnDraw();
}));
//當viewCanvas繪製時觸發
addDisposable(RxView.draws(viewCanvas)
.subscribe(o -> {
Log.e("rx_binding_test", "draws:viewCanvas繪製了");
}));複製程式碼
drag拖拽事件
RxView.drags(View view)
,內部封裝了OnDragListener拖拽監聽。
//當btnDraw被拖拽時觸發
addDisposable(RxView.drags(btnDraw)
.subscribe(o -> {
Log.e("rx_binding_test", "drags:btnDraw被拖拽了");
}));複製程式碼
layoutChange佈局改變事件
RxView.layoutChanges(View view)
,內部封裝了OnLayoutChangeListener佈局改變監聽。
//點選btnChange改變btn_layout的佈局,防抖2s
addDisposable(RxView.clicks(btnChange)
.throttleFirst(2, TimeUnit.SECONDS)
.subscribe(o -> btnLayout.layout(btnLayout.getLeft() - 20,
btnLayout.getTop(), btnLayout.getRight() - 20, btnLayout.getBottom())
));
//btn_layout佈局改變時觸發
addDisposable(RxView.layoutChanges(btnLayout)
.subscribe(o -> {
Log.e("rx_binding_test", "layoutChanges:btnLayout佈局改變了");
}));複製程式碼
scrollChange滑動事件
RxView.scrollChangeEvents(View view)
,內部封裝了OnScrollChangeListener滑動監聽。
//點選btnScroll模擬讓btnScrollLayout滑動
addDisposable(RxView.clicks(btnScroll)
.throttleFirst(2, TimeUnit.SECONDS)
.subscribe(o -> {
x += 10;
if (x == 100) {
x = 0;
}
btnScrollLayout.scrollTo(x, 0);
}));
//btnScrollLayout滑動時觸發
addDisposable(RxView.scrollChangeEvents(btnScrollLayout)
.subscribe(event -> {
Log.e("rx_binding_test", "scrollChangeEvents:btnScrollLayout滑動了:" + event.toString());
}));複製程式碼
View操作
RxView中還封裝了一些常用的例如setVisibility()
、setClickable()
等View操作。使用起來也很簡單,如下:
addDisposable(RxView.clicks(btnClick)
.throttleFirst(2, TimeUnit.SECONDS)
.subscribe(o -> {
RxView.visibility(btnClick).accept(true);
RxView.clickable(btnClick).accept(true);
RxView.enabled(btnClick).accept(true);
}));複製程式碼
這種操作方法單獨使用是需要進行try-catch的,但還記得RxJava2系列中我們學習到,RxJava2的Action與Function的回撥方法中都預設throws Exception,RxBinding也是如此。所以在觀察者中呼叫就無需try-catch了。
更多的操作可在RxView的原始碼中查到,基本上View中有的,J大神都編寫了,膜拜大神。
取消訂閱
最後別忘了在Activity銷燬時對建立的Disposable取消訂閱。Demo中的Act都以BaseActivity為基類,所以就無需再呼叫取消訂閱了,BaseActivity已經將這些工作做好了。
總結
RxBinding使用起來非常簡單,RxView中還有attaches、detaches,focusChanges,globalLayouts,hovers,touches等等就不一一演示了,碼友們可自行嘗試。
進階中的碼猿一枚,寫的不對的地方歡迎大神們留言指正,有什麼疑惑或者建議也可以在我Github上RxBindingDemo專案Issues中提出,我會及時回覆。
附上Demo的地址:
RxBindingDemo
另外:歡迎光臨我的Hexo個人部落格:Lei’s Blog