RxBinding系列之RxView(一)

前言

  自從用上RxJava後完全迷上Rx系列響應式編程,從本篇開始一塊兒來學習一下Rx套餐之一的RxBinding。RxBinding是什麼?它是一組開源庫,來自大神Jake Wharton之手,可將Android中各種UI控件的動做事件轉換爲RxJava中的數據流。也就是說使用RxBinding,咱們就能夠以RxJava的形式來處理UI事件。本篇主要講解其中RxView的相關View事件如何綁定。
  
  RxBinding中主要包含RxView、RxTextView、RxAdapterView、RxCompoundButton等等。因爲全寫一塊兒篇幅太長,我就一篇講解一種了。本系列主要講解以上經常使用的4種,詳細內容可飛機到:
  Jake Wharton的RxBindingjava

依賴

  本系列圍繞我本身編寫的RxBindingDemo來進行講解,項目中主要使用ButterKnife作View注入,RxBinding作事件綁定。RxBindingDemo代碼在文末有給地址。
  注意:RxBinding包中包含RxJava的內容,因此就無需再添加RxJava的依賴了。git

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的統一綁定與解綁。
  獻上代碼:github

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。從代碼看來是否是方便又簡潔呢,以往實現防抖還得添加各類標記,忒麻煩。ide

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拖拽監聽。this

//當btnDraw被拖拽時觸發
addDisposable(RxView.drags(btnDraw)
        .subscribe(o -> {
            Log.e("rx_binding_test", "drags:btnDraw被拖拽了");
        }));複製代碼

layoutChange佈局改變事件

  RxView.layoutChanges(View view),內部封裝了OnLayoutChangeListener佈局改變監聽。spa

//點擊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滑動監聽。code

//點擊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

相關文章
相關標籤/搜索