RxBinding系列之RxView(一)

前言

自從用上RxJava后徹底迷上Rx系列響應(yīng)式編程,從本篇開始一起來學(xué)習(xí)一下Rx套餐之一的RxBinding。RxBinding是什么?它是一組開源庫,來自大神Jake Wharton之手,可將Android中各類UI控件的動作事件轉(zhuǎn)換為RxJava中的數(shù)據(jù)流。也就是說使用RxBinding,我們就可以以RxJava的形式來處理UI事件。本篇主要講解其中RxView的相關(guān)View事件如何綁定。
  
RxBinding中主要包含RxView、RxTextView、RxAdapterView、RxCompoundButton等等。由于全寫一起篇幅太長,我就一篇講解一種了。本系列主要講解以上常用的4種,詳細(xì)內(nèi)容可飛機(jī)到:

Jake Wharton的RxBinding

依賴

本系列圍繞我自己編寫的RxBindingDemo來進(jìn)行講解,項(xiàng)目中主要使用ButterKnife做View注入,RxBinding做事件綁定。RxBindingDemo代碼在文末有給地址。

注意:RxBinding包中包含RxJava的內(nèi)容,所以就無需再添加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

相信學(xué)習(xí)過RxJava的碼友一定記得,使用RxJava實(shí)例化的Disposable需在不用時及時銷毀。
由于每個Activity中都寫一套add與clear的方法會造成代碼冗余,所以我將它們封裝到BaseActivity中方便統(tǒng)一對Disposable進(jìn)行管理,以及ButterKnife的統(tǒng)一綁定與解綁。

獻(xiàn)上代碼:

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點(diǎn)擊事件

clicks

RxView.clicks(View view),通過源碼可發(fā)現(xiàn)其內(nèi)部封裝了View.OnClickListener點(diǎn)擊監(jiān)聽,調(diào)用clicks方法返回一個Observable對象,每當(dāng)點(diǎn)擊這個View的時候,該Observable對象就會發(fā)射一個事件,隨即調(diào)用onNext()方法,Observable對應(yīng)的觀察者就可以通過onNext()回調(diào)響應(yīng)此次點(diǎn)擊事件。使用RxBinding還可做到點(diǎn)擊防抖的效果。來看代碼:

addDisposable(RxView.clicks(btnClick)
        .throttleFirst(2, TimeUnit.SECONDS)
        .subscribe(o -> {
            Log.e("rx_binding_test", "clicks:點(diǎn)擊了按鈕:兩秒內(nèi)防抖");
        }));

throttleFirst(long windowDuration, TimeUnit unit),設(shè)置一定時間內(nèi)只響應(yīng)首次(throttleFirst)或者末次(throttleLast)的點(diǎn)擊事件。windowDuration為防抖時間,unit為時間單位。調(diào)用這個方法便可防止短時間內(nèi)對View的重復(fù)點(diǎn)擊,本例中設(shè)置的防抖時間為2s。從代碼看來是不是方便又簡潔呢,以往實(shí)現(xiàn)防抖還得添加各種標(biāo)記,忒麻煩。

longClicks

RxView.longClicks(View view),內(nèi)部封裝了View.OnLongClickListener長按監(jiān)聽,原理同上。

addDisposable(RxView.longClicks(btnClick)
        .subscribe(o -> {
            Log.e("rx_binding_test", "longClicks:長點(diǎn)擊了按鈕");
        }));

draw繪制事件

RxView.draws(View view),內(nèi)部封裝了OnDrawListener繪制監(jiān)聽。

//點(diǎn)擊btnDraw調(diào)用viewCanvas的繪制
addDisposable(RxView.clicks(btnDraw)
        .throttleFirst(2, TimeUnit.SECONDS)
        .subscribe(o -> {
            //此處可模擬讓viewCanvas繪制
            //viewCanvas.getViewTreeObserver().dispatchOnDraw();
        }));
        
//當(dāng)viewCanvas繪制時觸發(fā)
addDisposable(RxView.draws(viewCanvas)
        .subscribe(o -> {
            Log.e("rx_binding_test", "draws:viewCanvas繪制了");
        }));

drag拖拽事件

RxView.drags(View view),內(nèi)部封裝了OnDragListener拖拽監(jiān)聽。

//當(dāng)btnDraw被拖拽時觸發(fā)
addDisposable(RxView.drags(btnDraw)
        .subscribe(o -> {
            Log.e("rx_binding_test", "drags:btnDraw被拖拽了");
        }));

layoutChange布局改變事件

RxView.layoutChanges(View view),內(nèi)部封裝了OnLayoutChangeListener布局改變監(jiān)聽。

//點(diǎn)擊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布局改變時觸發(fā)
addDisposable(RxView.layoutChanges(btnLayout)
        .subscribe(o -> {
            Log.e("rx_binding_test", "layoutChanges:btnLayout布局改變了");
        }));

scrollChange滑動事件

RxView.scrollChangeEvents(View view),內(nèi)部封裝了OnScrollChangeListener滑動監(jiān)聽。

//點(diǎn)擊btnScroll模擬讓btnScrollLayout滑動
addDisposable(RxView.clicks(btnScroll)
        .throttleFirst(2, TimeUnit.SECONDS)
        .subscribe(o -> {
            x += 10;
            if (x == 100) {
                x = 0;
            }
            btnScrollLayout.scrollTo(x, 0);
        }));
        
//btnScrollLayout滑動時觸發(fā)
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);
        }));

這種操作方法單獨(dú)使用是需要進(jìn)行try-catch的,但還記得RxJava2系列中我們學(xué)習(xí)到,RxJava2的Action與Function的回調(diào)方法中都默認(rèn)throws Exception,RxBinding也是如此。所以在觀察者中調(diào)用就無需try-catch了。

更多的操作可在RxView的源碼中查到,基本上View中有的,J大神都編寫了,膜拜大神。

取消訂閱

最后別忘了在Activity銷毀時對創(chuàng)建的Disposable取消訂閱。Demo中的Act都以BaseActivity為基類,所以就無需再調(diào)用取消訂閱了,BaseActivity已經(jīng)將這些工作做好了。

總結(jié)

RxBinding使用起來非常簡單,RxView中還有attaches、detaches,focusChanges,globalLayouts,hovers,touches等等就不一一演示了,碼友們可自行嘗試。

進(jìn)階中的碼猿一枚,寫的不對的地方歡迎大神們留言指正,有什么疑惑或者建議也可以在我Github上RxBindingDemo項(xiàng)目Issues中提出,我會及時回復(fù)。

附上Demo的地址:
RxBindingDemo
  
另外:歡迎光臨我的Hexo個人博客:Lei’s Blog

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,741評論 25 709
  • Github:https://github.com/ReactiveX/RxJavahttps://github....
    才兄說閱讀 1,712評論 2 10
  • 前言 我從去年開始使用 RxJava ,到現(xiàn)在一年多了。今年加入了 Flipboard 后,看到 Flipboar...
    AWeiLoveAndroid閱讀 2,988評論 4 42
  • 巧克力是屋頂 餅干是墻壁 落下的凱凱白雪是鮮奶冰淇淋 覆蓋了卡布奇諾的大地 樹干上的冰棱奶糖一般美好 白雪公主降生...
    木偶Devil11閱讀 226評論 1 3

友情鏈接更多精彩內(nèi)容