框架:RxJava2.X(RxAndroid2.X)

RxJava官方Github地址沒有任何資料能比官方更棒的了,快去看看吧。

大神拋物線的講解RxJava1.x的講解,然後去使用,結果發現官方已經重構了RxJava,推出全新的2.+版本。

介紹

  1. RxAndroid是RxJava在Android上的一個擴展,大牛JakeWharton的項目。據說和Retorfit、OkHttp組合起來使用,效果不是一般的好。而且用它似乎可以完全替代eventBus和OTTO,這麼牛的東西當然要研究研究了
    ,看看它到底有多厲害。

  2. RxJava是幹嘛的:Rx(Reactive Extensions)是一個庫,用來處理事件和異步任務,在很多語言上都有實現,RxJava是Rx在Java上的實現。簡單來說,RxJava就是處理異步的一個庫,最基本是基於觀察者模式來實現的。通過Obserable和Observer的機制,實現所謂響應式的編程體驗。
      Android的童鞋都知道,處理異步事件,現有的AsyncTask、Handler,不錯的第三方事件總線EventBus、OTTO等等都可以處理。並且大部分童鞋應該都很熟練了。而且經我目前的學習來看,RxJava這個庫,上手確實有門檻,不是拿來就能用。但是作爲一個猿,那些可能出現的優秀的框架技術,及時的跟進和學習是必要的,從中汲取營養才能幫助自己成長。況且有童鞋已經表示,它完全可以替代EventBus和OTTO,來看看吧。

  3. RxJava的優勢
    最概括的兩個字:簡潔。而且當業務越繁瑣越複雜時這一點就越顯出優勢——它能夠保持簡潔。
      簡單的demo看不出來,真正投入項目使用了應該就有體會了。它提供的各種功能強悍的操作符真的很強大。

記住幾個單詞:
被觀察者Observable
觀察者Observer
訂閱subscribe
取消訂閱Disposable
別被這幾個單詞給繞暈了哈,其實沒想象中的那麼難,剛開始就是背單詞繞暈了覺得好難啊,理清思路後發現很容易理解的,其實就是異步操作+各種回調。

可以這樣理解:被觀察者Observable就像小偷,觀察者Observer就像警察,訂閱subscribe就像警察時刻觀察者小偷,一旦小偷有任何動作,警察馬上作出應對;小偷有可能做出一連續的動作,警察就必須對應做出一連續的應對。

一、添加依賴

目前最新版本

implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.7'

二、單獨使用

2.+比1.+多了Disposable (當然多的可不止這一個哈),它可以用來主動取消訂閱dispose()、查詢是否解除訂閱 true 代表 已經解除訂閱isDisposed()。

xjava雖然好用,但是總所周知,容易遭層內存泄漏。也就說在訂閱了事件後沒有及時取閱,導致在activity或者fragment銷燬後仍然佔用着內存,無法釋放。而disposable便是這個訂閱事件,可以用來取消訂閱。

1、基本使用 + 主動解除訂閱 Disposable.dispose()

整體樣子長這樣滴,必須自己慢慢敲一遍代碼纔能有一定的理解:

  1. 初始化被觀察者Observable:使用 Observable.create(ObservableOnSubscribe
    source),必須實現subscribe()方法。

  2. 訂閱subscribe():給被觀察者綁定觀察者Observer,使用subscribe(Observer<? super T>
    observer);

  3. 初始化觀察者Observer;

        //1、初始化被觀察者Observable:使用 create()
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {            
            }
            //2、訂閱subscribe():給被觀察者綁定觀察者Observer
        }).subscribe(new Observer<Integer>() { //3、初始化觀察者Observer
            @Override
            public void onSubscribe(Disposable d) {
            }

            @Override
            public void onNext(Integer integer) {               
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onComplete() {
            }
        });

接下來就是加入我們的邏輯啦:

        //1、初始化被觀察者Observable:使用create()
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                Log.e(TAG, "Observable emit 1" + "\n");
                Log.e(TAG, "subscribe中isDisposable:" + emitter.isDisposed()+ "\n");
                emitter.onNext(1);
                Log.e(TAG, "Observable emit 2" + "\n");
                Log.e(TAG, "subscribe中isDisposable:" + emitter.isDisposed()+ "\n");
                emitter.onNext(2);
                Log.e(TAG, "Observable emit 3" + "\n");
                Log.e(TAG, "subscribe中isDisposable:" + emitter.isDisposed()+ "\n");
                emitter.onNext(3);
                Log.e(TAG, "Observable emit 4" + "\n");
                Log.e(TAG, "subscribe中isDisposable:" + emitter.isDisposed()+ "\n");
                emitter.onNext(4);
                Log.e(TAG, "Observable emit 5" + "\n");
                Log.e(TAG, "subscribe中isDisposable:" + emitter.isDisposed()+ "\n");
                emitter.onNext(5);
            }
            //2、訂閱subscribe():給被觀察者綁定觀察者Observer
        }).subscribe(new Observer<Integer>() { //3、初始化觀察者Observer

            private int i;
            private Disposable mDisposable;

            @Override
            public void onSubscribe(Disposable d) {
                mDisposable = d;
                Log.e(TAG, "onSubscribe中isDisposable:" + d.isDisposed()+ "\n");
            }

            @Override
            public void onNext(Integer integer) {
                i++;
                if (i == 2) {
                     // 在RxJava 2.x 中,新增的Disposable可以主動解除訂閱,
                    // 讓Observer觀察者不再接收Observable被觀察者的事件
                    Log.e(TAG, "onNext中dispose()之前,isDisposable:" + mDisposable.isDisposed()+ "\n");
                    mDisposable.dispose();
                    Log.e(TAG, "onNext中dispose()之後,isDisposable:" + mDisposable.isDisposed()+ "\n");
                }
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError中isDisposable:" + mDisposable.isDisposed()+ "\n");
                Log.e(TAG, "onError : value : " + e.getMessage() + "\n" );
            }

            @Override
            public void onComplete() {
                 Log.e(TAG, "onComplete中isDisposable:" + mDisposable.isDisposed()+ "\n");
                 Log.e(TAG, "onComplete" + "\n" );
            }
        });

運行結果:

在這裏插入圖片描述
這裏就是RxJava最基本的寫法,還要再說一下,subscribe的方法重載,subscribe()方法裏什麼參數也不放是空實現,也就是說被觀察者無論發生什麼,觀察者都不關心。

如果觀察者只關心onNext方法裏的內容,可以直接重載subscribe(Consumer<? spuer T> onNext)這個方法,會減少代碼。

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
            }
        }).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                //回調後在UI界面上展示出來
            }
        });

2、被觀察者使用onComplete()

被觀察者使用onComplete()表示觀察者完成訂閱,即觀察者會調用onComplete()方法:

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                Integer[] integers = {0, 1, 2, 3, 4};
                for (int i = 0; i < integers.length; i++) {
                    Log.d(TAG, "=====第" + i + "次,發:" + i);
                    emitter.onNext(integers[i]);
                    if (i == 1) {
                        emitter.onComplete();
                    }
                }
            }
        }).subscribe(new Observer<Integer>() {
            int i = 0;

            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "Observer的onSubscribe");
            }

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG, "第" + i + "次,收:" + integer);
                i++;
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "Throwable");
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete");
            }
        });

注意:

 emitter.onNext(integers[i]);
 if (i == 3) {
     emitter.onComplete();
 }

一旦調用onComplete()則觀察者會執行完成方法。
運行結果:
在這裏插入圖片描述
當調換onComplete()onNext(integers[i])的順序:

if (i == 1) {
     emitter.onComplete();
 }
 Log.d(TAG, "=====第" + i + "次,發:" + i);
emitter.onNext(integers[i]);

運行結果:
在這裏插入圖片描述
總結:當調用emitter.onComplete();後訂閱關係表示完成,觀察者將不會做出響應,但並不影響被觀察者。上游的onNext對應下游的OnNext,上游的onComplete對應下游的onComplete。

還沒懂那看看RxJava2.0——從放棄到入門 - 簡書- 肖邦kaka

3、觀察者使用dispose()

觀察者使用dispose()取消訂閱,觀察者不會調用onComplete():

 Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                Integer[] integers = {0, 1, 2, 3, 4};
                for (int i = 0; i < integers.length; i++) {
                    Log.d(TAG, "=====第" + i + "次,發:" + i);
                    emitter.onNext(integers[i]);
                }
            }
        }).subscribe(new Observer<Integer>() {
            Disposable disposable;
            int i = 0;

            @Override
            public void onSubscribe(Disposable d) {
                disposable = d;
                Log.d(TAG, "賦值disposable:dispose0 = " + disposable.isDisposed());
                Log.d(TAG, "Observer的onSubscribe");
            }

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG, "第" + i + "次,收:" + integer);
                Log.d(TAG, "dispose1 = " + disposable.isDisposed());
                if(i==2){
                    disposable.dispose();
                }
                Log.d(TAG, "dispose2 = " + disposable.isDisposed());
                i++;
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "Throwable");
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete");
            }
        });

運行結果:
在這裏插入圖片描述
可以看到當執行完

 if(i==2){
      disposable.dispose();
 }

之後dispose2 = true,觀察者已經不再處理事件了,因爲此方法已經取消了訂閱。

4、被觀察者的onComplete()+觀察者的dispose()

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                Integer[] integers = {0, 1, 2, 3, 4};
                for (int i = 0; i < integers.length; i++) {
                    if (i == 1) {
                        emitter.onComplete();
                    }
                    Log.d(TAG, "=====第" + i + "次,發:" + i);
                    emitter.onNext(integers[i]);
                }
            }
        }).subscribe(new Observer<Integer>() {
            Disposable disposable;
            int i = 0;

            @Override
            public void onSubscribe(Disposable d) {
                disposable = d;
                Log.d(TAG, "賦值disposable:dispose0 = " + disposable.isDisposed());
                Log.d(TAG, "Observer的onSubscribe");
            }

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG, "第" + i + "次,收:" + integer);
                Log.d(TAG, "dispose1 = " + disposable.isDisposed());
                if(i==2){
                    disposable.dispose();
                }
                Log.d(TAG, "dispose2 = " + disposable.isDisposed());
                i++;
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "Throwable");
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete");
            }
        });

運行結果:
在這裏插入圖片描述
總結:
1、被觀察者使用一次onNext(),對應的觀察者就會調用一次onNext(),同理onComplete()這些一樣的。
2、被觀察者使用onComplete(),觀察者運行onComplete()之後就不再做處理了。
3、觀察者使用disposable.dispose();,觀察者不會運行onComplete(),直接不對被觀察者的動作做出反應。

二、線程切換

RxJava 中已經內置了很多線程選項供我們選擇,例如有:
1、Schedulers.io() 代表io操作的線程, 通常用於網絡,讀寫文件等io密集型的操作;
2、Schedulers.computation() 代表CPU計算密集型的操作, 例如需要大量計算的操作;
3、Schedulers.newThread() 代表一個常規的新線程;
4、AndroidSchedulers.mainThread() 代表Android的主線程

推薦查看教你輕鬆理解Rxjava之線程切換流程(observeOn與subscribeOn) - wenyingzhi的博客 - CSDN博客 輕鬆理解線程切換流程。當然你也可以這裏滴。

整體樣子張這樣滴:

 Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
            }
        }).subscribeOn(Schedulers.io())
        .map(new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer integer) throws Exception {
                return integer;
            }
        }).doOnSubscribe(new Consumer<Disposable>() {
            @Override
            public void accept(Disposable disposable) throws Exception {
            }
        }).subscribeOn(AndroidSchedulers.mainThread())
        .doOnSubscribe(new Consumer<Disposable>() {
            @Override
            public void accept(Disposable disposable) throws Exception {      
            }
        }).subscribeOn(Schedulers.io())
        .observeOn(Schedulers.io())
        .flatMap(new Function<Integer, ObservableSource<Integer>>() {
            @Override
            public ObservableSource<Integer> apply(Integer integer) throws Exception {         
                return Observable.fromArray(integer);
            }
        }).observeOn(AndroidSchedulers.mainThread()) 
                .subscribe(new Observer<Integer>() {               
                    @Override
                    public void onSubscribe(Disposable d) {                    
                    }

                    @Override
                    public void onNext(Integer bytes) {                   
                    }

                    @Override
                    public void onError(Throwable e) {
                    }

                    @Override
                    public void onComplete() {                     
                    }
                });

別被這個樣子給嚇住了,只是一口氣使用了很多切換線程+操作符而已,沒問題滴。
看我們不停地切換線程吧,接下來加入我們的處理,主要就是打印出每次的線程具體是哪一個:

  Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                Log.d(TAG, "4、Observable的create:" + Thread.currentThread().getName());
                e.onNext(1);//發射數據,向下走
            }
        }).subscribeOn(Schedulers.io())//S1、subscribeOn切換訂閱線程, io操作的線程
        .map(new Function<Integer, Integer>() {//map:數據流的操作符,主要是對數據處理
            @Override
            public Integer apply(Integer integer) throws Exception {
                Log.d(TAG, "5、map:" + Thread.currentThread().getName());
                return integer;
            }
        }).doOnSubscribe(new Consumer<Disposable>() {
            @Override
            public void accept(Disposable disposable) throws Exception {
                Log.d(TAG, "3、doOnSubscribe1:" + Thread.currentThread().getName());
            }
        }).subscribeOn(AndroidSchedulers.mainThread())//S2、subscribeOn切換訂閱線程, Android的主線程
        .doOnSubscribe(new Consumer<Disposable>() {
            @Override
            public void accept(Disposable disposable) throws Exception {
                Log.d(TAG, "2、doOnSubscribe2:" + Thread.currentThread().getName());
            }
        }).subscribeOn(Schedulers.io())//S3、subscribeOn切換訂閱線程, io操作的線程
        .observeOn(Schedulers.io())//O1、observeOn處理數據流方向, io操作的線程
        .flatMap(new Function<Integer, ObservableSource<Integer>>() {//flatMap:數據流的操作符,主要是對數據處理
            @Override
            public ObservableSource<Integer> apply(Integer integer) throws Exception {
                Log.d(TAG,"6、flatMap:" + Thread.currentThread().getName());
                return Observable.fromArray(integer);
            }
        }).observeOn(AndroidSchedulers.mainThread())//O2、observeOn處理數據流方向, Android的主線程
                //調用subscribe發起訂閱
                .subscribe(new Observer<Integer>() {
                    private Disposable mDisposable;//Disposable用於解除訂閱

                    @Override
                    public void onSubscribe(Disposable d) {
                        //發起訂閱,向上走
                        Log.d(TAG, "1、Observer的subscribe:" + Thread.currentThread().getName());
                    }

                    @Override
                    public void onNext(Integer bytes) {
                        //執行結束
                        Log.d(TAG, "7、Observer的onNext:" + Thread.currentThread().getName());
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "Observer的onError:" + Thread.currentThread().getName());
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "onComplete:" + Thread.currentThread().getName());
                    }
                });

運行效果:
在這裏插入圖片描述
現在我們來講解一下吧:

理解RxJava的操作方向:

  1. 訂閱,向上走的一個過程
  2. 數據流,向下走的一個過程數據流,向下走的一個過程
    在這裏插入圖片描述
    務必記住這幾點:
    訂閱的操作符:create丶doOnSubscribe
    數據流的操作符:map丶flatMap丶過濾等主要是對數據處理的操作符
    走之前記住一句話:subscribeOn切換訂閱線程,observeOn處理數據流方向
    1:當我們調用了subscribe的發起訂閱
    2:向上走,我只需要關心subscribeOn和訂閱的操作符
    3:向下走,我只需要關心observeOn和數據流的操作符

發起訂閱,即流程的起始點:代碼中.subscribe(new Observer<Integer>() { @Override public void onSubscribe(Disposable d) { //發起訂閱,向上走 }...)這裏是發起訂閱,起始點。

1、開始,發起訂閱:
當前線程狀態(main線程)

訂閱,向上走
經過第一個操作符observeOn,是控制數據流線程的,跳過
經過flatMap處理數據流的操作符,跳過
經過observeOn跳過
經過subscribeOn,將線程切換到IO線程,現在訂閱處於IO線程
經過doOnSubscribe,執行裏面代碼,在IO線程中執行 輸出:doOnSubscribe2:RxCachedThreadScheduler-1
經過subscribeOn,將線程切換到main線程,現在訂閱處於main線程
經過doOnSubscribe,執行裏面代碼,在main線程中執行 輸出:doOnSubscribe1:main
經過map方法,處理數據流的方法,跳過
經過subscribeOn,將線程切換到IO線程,現在訂閱處於IO線程
經過create方法,在IO線程中執行 輸出:create:RxCachedThreadScheduler-1
訂閱完成,開始發射數據 注意:從上面結束我們知道,當前處於IO線程哦

2、當前線程狀態(IO線程):發射數據

發射數據,向下走
經過subscribeOn跳過
經過map,在IO線程中執行 輸出:map1:RxCachedThreadScheduler-1
經過doOnSubscribe跳過
經過subscribeOn跳過
經過doOnSubscribe跳過
經過subscribeOn跳過
經過observeOn,將線程切換到IO線程
經過flatMap執行,在IO線程執行 輸出:flatMap:RxCachedThreadScheduler-2
經過observeOn,將線程切換到main線程
結束執行onNext方法,在main線程輸出:執行完畢:main

三、RxJava+OkHttp

實現的效果:點擊按鈕,獲取網絡圖片並加載到界面上。

1、使用OkHttp獲取網絡圖片工具類

專門寫一個工具類DownLoadUtils來單獨處理使用OkHttp獲取網絡圖片:

public class DownLoadUtils {
    private OkHttpClient client;
    public DownLoadUtils(){
        client = new OkHttpClient();
    }
    public Observable<byte[]> downLoadImage(String path){
        return Observable.create(new ObservableOnSubscribe<byte[]>() {
            @Override
            public void subscribe(ObservableEmitter<byte[]> emitter) throws Exception {
                if(!emitter.isDisposed()){//isDisposed()查詢是否解除訂閱 true 代表 已經解除訂閱
                    //訪問網絡操作
                    Request request = new Request.Builder().url(path).build();
                    client.newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            emitter.onError(e);
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            if(response.isSuccessful()){
                                byte[] data = response.body().bytes();
                                if(data != null){
                                    emitter.onNext(data);
                                }
                            }
                            emitter.onComplete();
                        }
                    });
                }
            }
        });
    }
}

傳過來網絡圖片地址,初始化被觀察者Observable.create),沒有解除訂閱的話,就進行訪問網絡操作。
網絡請求成功則把獲取到的數據傳遞給ObservableEmitter,使用emitter.onNext(data);失敗了則把錯誤傳給它emitter.onError(e);

2、活動使用

圖片地址private String PATH = "http://pic32.nipic.com/20130829/12906030_124355855000_2.png";,就是在百度圖片上隨便找的。

private DownLoadUtils utils;//下載圖片工具類

點擊按鈕後執行的事件:

                //使用HTTP協議獲取數據
                //subscribeOn(Schedulers.io()):I/O操作線程,通常用於網絡,讀寫文件等io密集型的操作
                //observeOn(AndroidSchedulers.mainThread()):Android主線程
                utils.downLoadImage(PATH).subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Observer<byte[]>() {
                            private Disposable mDisposable;//Disposable用於解除訂閱

                            @Override
                            public void onSubscribe(Disposable d) {
                                //訂閱
                                mDisposable = d;                               
                            }

                            @Override
                            public void onNext(byte[] bytes) {
                                //更新界面
                                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
                                imageView.setImageBitmap(bitmap);
                                //判斷mDisposable.isDisposed()如果解除了則不需要處理
                            }

                            @Override
                            public void onError(Throwable e) {
                                showToast("報錯"+e.getMessage());
                                mDisposable.dispose();//主動解除訂閱
                            }

                            @Override
                            public void onComplete() {
                                showToast("完成");
                                mDisposable.dispose();//主動解除訂閱
                            }
                        });

到了這裏RxJava的基礎使用和基本流程算應該能理解了,接下來就是各種操作符啦,可以看看這個系列,它主要是講解多種操作符這可能是最好的RxJava 2.x 教程(完結版) - 簡書 或者看官方講解

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