安卓開發進階之RxJava在實際項目中使用--第一篇

關於RxJava原理分析,請參考仍物線寫的文章—-給 Android 開發者的 RxJava 詳解。本文不對原理作過多的分析,從最快上手的角度,讓開發者使用起來,當我們有實踐經驗後回過頭來看原理分析會更清晰。
本系列共有三篇文章,分別關於Rxjava的基礎使用(最快,最實用),Retrofit使用(Github上star達22k+,安卓領域排名第一),最後是RxCache緩存(大部分app都支持離線查看功能)。
安卓開發進階之RxJava在實際項目中使用–第二篇

本文是第一篇,從防止重複點擊,監聽內容變化,延遲操作,週期性操作,RxJava的生命週期管理,監聽網絡狀態和權限管理七個方面介紹,這些都是我在實際項目使用到的,不是理論上的介紹。

先來看完整的運行效果
這裏寫圖片描述

一、防止重複點擊

首先添加引用

    compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'

添加代碼

RxView.clicks(tv1).throttleFirst(2, TimeUnit.SECONDS)
                .subscribe(new Consumer<Object>() {
            @Override
            public void accept(Object o) throws Exception {
                Log.d("tvClick","2秒內只能點擊一次");
                Toast.makeText(MainActivity.this,"2秒內只能點擊一次",Toast.LENGTH_LONG).show();
            }
        });

運行效果
這裏寫圖片描述

二、監聽內容變化

不需要重寫EditText控件的textWacher,然後寫一大堆代碼了,看看下面是如何優雅的實現的。
監聽單個輸入框內容

RxTextView.textChanges(et1).skip(1).subscribe(new Consumer<CharSequence>() {
            @Override
            public void accept(CharSequence charSequence) throws Exception {
                if (TextUtils.isEmpty(charSequence.toString())) enableButton(btn1,false,0.2f);
                else enableButton(btn1,true,1f);
            }
        });

監聽多個輸入框內容

Observable<CharSequence> ob1= RxTextView.textChanges(et2).skip(1);
        Observable<CharSequence> ob2= RxTextView.textChanges(et3).skip(1);
        Observable.combineLatest(ob1, ob2, new BiFunction<CharSequence, CharSequence, Boolean>() {
            @Override
            public Boolean apply(CharSequence charSequence, CharSequence charSequence2) throws Exception {
                return !TextUtils.isEmpty(charSequence) && !TextUtils.isEmpty(charSequence2);//返回值可以自定義,比如至少6位
            }
        }).subscribe(new Consumer<Boolean>() {
            @Override
            public void accept(Boolean aBoolean) throws Exception {//aBoolean值來源於上面apply方法的返回值
                if (aBoolean) enableButton(btn2,true,1f);
                else enableButton(btn2,false,0.2f);
            }
        });

這裏寫圖片描述
三、延遲操作

     Observable.timer(3,TimeUnit.SECONDS).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Consumer<Long>() {
                            @Override
                            public void accept(Long aLong) throws Exception {                               Toast.makeText(MainActivity.this,"RxJava延遲3秒操作",Toast.LENGTH_LONG).show();
                            }
                        });

這裏寫圖片描述

四、週期性操作

週期性操作再也不用自帶的Timer,不用new Timer(), new TimeTask(),這樣寫的零零散散,使用RxJava,讓一切優雅起來。。。

     Observable.interval(3,TimeUnit.SECONDS).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Consumer<Long>() {
                            @Override
                            public void accept(Long aLong) throws Exception {
                                Toast.makeText(MainActivity.this,"RxJava間隔3秒週期性操作,當前時間:"+System.currentTimeMillis(),Toast.LENGTH_LONG).show();
                            }
                        });

如果上面代碼中沒有設置運行所在的線程subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())則會報錯
io.reactivex.exceptions.OnErrorNotImplementedException: Can’t create handler inside thread that has not called Looper.prepare()
這裏寫圖片描述

從上面的運行效果可以看到退出app後該定時操作沒有被取消,所以就有了下面對RxJava的生命週期管理工–RxLifeCycle。

五、LifeCycle生命週期管理(針對上面的週期性操作

RxLifeCycle地址

先添加Maven庫

        maven { url "https://www.jitpack.io" }

然後添加引用

    compile 'com.github.nekocode.rxlifecycle:rxlifecycle:1.1'
                    @Override
                    public void accept(Long aLong) throws Exception {
                        Toast.makeText(MainActivity.this,"RxJava間隔3秒週期性操作,RxLifeCycle進行生命週期管理",Toast.LENGTH_LONG).show();
                    }
                });

第四、五兩種週期性操作的區別在於Activity銷燬後此操作是否能被取消,很明顯,後者可以,這也是LifeCycle存在的意義。

這裏寫圖片描述

六、監聽網絡狀態

reactivenetwork地址

    compile 'com.github.pwittchen:reactivenetwork-rx2:0.9.1'
ReactiveNetwork.observeNetworkConnectivity(MainActivity.this).subscribe(new Consumer<Connectivity>() {
            @Override
            public void accept(@NonNull Connectivity connectivity) throws Exception {
                if (connectivity.getState() == NetworkInfo.State.CONNECTED) {
                    Toast.makeText(MainActivity.this,"RxJava檢測到網絡已連接",Toast.LENGTH_LONG).show();
                }
                else{
                    Toast.makeText(MainActivity.this,"RxJava檢測到網絡已斷開",Toast.LENGTH_LONG).show();
                }
            }
        });

看了這種實現,你還會去繼承BroadcastReciver,然後去Manifests.xml裏面註冊嗎?然後通過接口回調?太麻煩了。去試試這種簡單明瞭的方式吧。

七、權限管理管理

RxPermissions地址

 compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar'
RxPermissions rxPermissions=new RxPermissions(this);
        RxView.clicks(findViewById(R.id.getPermissionBtn))
                .compose(rxPermissions.ensure(Manifest.permission.WRITE_EXTERNAL_STORAGE))
                .subscribe(
                        new Consumer<Boolean>() {
                    @Override
                    public void accept(@NonNull Boolean aBoolean) throws Exception {
                        if (aBoolean)  Toast.makeText(MainActivity.this,"已獲取該權限",Toast.LENGTH_LONG).show();
                        else Toast.makeText(MainActivity.this,"無法獲取該權限",Toast.LENGTH_LONG).show();
                    }
                }
                );

演示中之所以“無法獲取該權限”,是因爲沒有在配置文件Manifests.xml中申請權限,一旦配置了該權限即返回true。另外,RxPermissions的主要用於Android6.0動態申請權限,通過對話框獲取用戶授權,而演示模擬器低於Android6.0,所以沒有彈出對話框。

至此 ,上面所有的代碼及其效果都給大家展示了,相信大家都學會了使用。如果有什麼疑問,可以查看我提供的源碼Demo。下一篇,我將介紹安卓領域網絡請求框架中的宇宙大帝–Retrofit。拭目以待吧。。。

點此下載源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章