RxAndroid結合Retrofit,看看誰纔是最佳拍檔!

這篇博文醞釀很久了,今天終於下定決心開始寫!RxAndroid和Retrofit都算是當下很是流行的Android開發框架,這兩個框架光是單獨使用就已經爽歪歪了,那麼將RxAndroid和Retrofit結合起來,又會有怎樣的效果呢?java

鑑於不少小夥伴可能還沒用過RxJava或者RxAndroid,因此我打算先來介紹一下RxJava和RxAndroid,而後再來介紹RxAndroid和Retrofit組合拳!!react

本文主要包括如下三方面內容:android

1.RxJava簡介git

2.RxJava在Android中的使用github

3.RxJava配合Retrofit的使用web

OK,廢話很少說,那就開始吧!編程

1.RxJava簡介

RxJava做爲Android開發者的新寵已經有很長一段時間了,用過RxJava的人,都以爲這個東西簡單好用,沒用過的小夥伴第一次看到RxJava的代碼時可能會以爲這個東西很是繁瑣,那麼今天,我想經過幾個簡單的非HelloWorld的案例來讓你們完全理解RxJava的使用。api

先來看看RxJava的GitHub地址:數組

https://github.com/ReactiveX/RxJava網絡

將RxJava引入到咱們的項目中:

compile 'io.reactivex:rxandroid:1.1.0'
    compile 'io.reactivex:rxjava:1.1.0'

那麼學習RxJava,先得弄清楚什麼是RxJava,關於RxJava的介紹,GitHub上有一句話,

a library for composing asynchronous and event-based programs by using observable sequences.

翻譯成中文就是:

RxJava是一個基於可觀測序列組成的異步的、基於事件的庫。通俗一點說就是RxJava它是一個異步庫,這個異步庫可讓咱們用很是簡潔的代碼來處理複雜數據流或者事件。OK,那麼這是對RxJava的一個基本介紹,接下來咱們再來看看RxJava中兩個最最基礎的概念,一個是Observable,還有一個是Observer,其中Observable咱們稱之爲被觀察者,Observer稱之爲觀察者,Observable用戶發送消息,而Observer用於消費消息,在實際開發中,咱們更多的是選擇Observer的一個子類Subscriber來消費消息。在消息發送的過程當中,Observable能夠發送任意數量任意類型的消息(甚至一個將一個觸摸事件看成一個消息發出),當Observable所發送的消息被成功處理或者消息出錯時,一個流程結束。Observable會用它的每個Subscriber(觀察者)的onNext方法進行消息處理,在消息成功處理後以onComplete()方法結束流程,若是消息在處理的過程當中出現了任何異常,則以onError()方法結束流程。好比下面幾行代碼:

Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("哈哈哈哈");
                subscriber.onNext("lalalala");
                subscriber.onCompleted();
            }
        })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {
                        Log.d("google_lenve_fb", "onCompleted: onCompleted()");
                    }

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

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve_fb", "onNext: " + s);
                    }
                });

經過調用Observable的create方法來建立一個消息源,在它的onCall方法調用next方法來發送兩條消息,當兩條消息發送完成以後,調用onComplete方法表示消息發送完畢!subscribe表示訂閱一條消息,在訂閱的時候咱們能夠傳入一個Observer對象,也能夠傳入一個Subscriber對象,這兩個對象中的方法都是同樣的,在onNext方法中處理消息,當消息處理完成以後會自動的調用onComplete方法,若是消息處理過程當中出錯,則會調用onError方法,上面方法打印的日誌以下:

onNext: 哈哈哈哈
onNext: lalalala
onCompleted: onCompleted()

若是我在onNext方法執行一行  1/0 ,onNext方法改爲下面的樣子:

@Override
                    public void onNext(String s) {
                        Log.d("google_lenve_fb", "onNext: " + s);
                        int i = 1 / 0;
                    }

這個時候再運行,系統打印的日誌以下:

onNext: 哈哈哈哈
onError:onError() 

當第一條消息打印出來以後,執行1/0時拋異常,直接調用了onError方法,第二條消息將再也不處理。OK,上面的代碼是一個小小的案例,RxJava中還有許多好玩的操做符,咱們接下來一個一個來看。

在實際開發中,咱們的數據來源多是多種多樣的,爲了簡化數據操做,Observable類爲咱們提供了許多現成的方法,這些方法都可以極大的簡化咱們對數據的操做,一個一個來看吧。

1.1 from函數

Observale中的from函數接受一個數組,這個方法返回一個按數組元素的順序來發射這些數據的Observale,看看下面一行代碼:

Observable.from(new String[]{"竹外桃花三兩枝", "春江水暖鴨先知"})
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve_fb", "onNext: " + s);
                    }
                });

這裏的觀察者我使用了Subscriber,它是Observer的一個實現類。這裏打印的結果以下:

D/google_lenve_fb: onNext: 竹外桃花三兩枝
D/google_lenve_fb: onNext: 春江水暖鴨先知

按順序將from函數中數組的值一個一個打印出來了。OK,接着往下看:

1.2  just函數

just函數它接受最多10個參數,返回一個按參數順序發射這些數據的Observable,代碼以下:

Observable.just("Hello", "World", "Hello", "RxJava!","塞外秋來風景異","衡陽雁去無留意"
        ,"四面邊聲連角起","千嶂裏","長煙落日孤城閉","濁酒一杯家萬里")
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve_fb", "onNext: " + s);
                    }
                });

打印結果以下:

D/google_lenve_fb: onNext: Hello
D/google_lenve_fb: onNext: World
D/google_lenve_fb: onNext: Hello
D/google_lenve_fb: onNext: RxJava!
D/google_lenve_fb: onNext: 塞外秋來風景異
D/google_lenve_fb: onNext: 衡陽雁去無留意
D/google_lenve_fb: onNext: 四面邊聲連角起
D/google_lenve_fb: onNext: 千嶂裏
D/google_lenve_fb: onNext: 長煙落日孤城閉
D/google_lenve_fb: onNext: 濁酒一杯家萬里

1.3map函數

map函數能夠對Observable建立的原始數據進行二次加工,而後再被觀察者獲取。好比下面一段代碼,我給原始數據的每一項都追加一個字符串,而後返回:

Observable.from(new String[]{"醉裏挑燈看劍","夢迴吹角連營"})
                .map(new Func1<String, String>() {
                    @Override
                    public String call(String s) {
                        return s + "---辛棄疾";
                    }
                })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve_fb", "onNext: " + s);
                    }
                });

打印結果以下:

D/google_lenve_fb: onNext: 醉裏挑燈看劍---辛棄疾
D/google_lenve_fb: onNext: 夢迴吹角連營---辛棄疾

RxJava的使用都是鏈式編程,使用map函數時數據來源能夠各類各樣。

1.4flatMap函數

flatMap函數接受一個Observable函數做爲輸入函數,而後在這個輸入的基礎上再建立一個新的Observable進行輸出,好比下面一段代碼:

Observable.just("落霞與孤鶩齊飛", "秋水共長天一色")
                .flatMap(new Func1<String, Observable<String>>() {
                    @Override
                    public Observable<String> call(String s) {
                        return Observable.from(new  String[]{s + "馮唐易老", s + "李廣難封"});
                    }
                }).subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {
                Log.d("google_lenve_fb", "onNext: " + s);
            }
        });

打印結果:

D/google_lenve_fb: onNext: 落霞與孤鶩齊飛馮唐易老
D/google_lenve_fb: onNext: 落霞與孤鶩齊飛李廣難封
D/google_lenve_fb: onNext: 秋水共長天一色馮唐易老
D/google_lenve_fb: onNext: 秋水共長天一色李廣難封

1.5 scan函數

scan函數是一個累加器函數,對於Observable發射的每項數據進行累加,並將累加的結果返回,以下:

Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
                .scan(new Func2<Integer, Integer, Integer>() {
                    @Override
                    public Integer call(Integer integer, Integer integer2) {
                        return integer + integer2;
                    }
                })
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.d("google_lenve_fb", "onNext: " + integer);
                    }
                });
        Observable.from(new String[]{"明", "月", "別", "枝", "驚", "鵲"})
                .scan(new Func2<String, String, String>() {
                    @Override
                    public String call(String s, String s2) {
                        return s + s2;
                    }
                })
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve", "onNext: " + s);
                    }
                });

打印結果以下:

D/google_lenve_fb: onNext: 1
D/google_lenve_fb: onNext: 3
D/google_lenve_fb: onNext: 6
D/google_lenve_fb: onNext: 10
D/google_lenve_fb: onNext: 15
D/google_lenve_fb: onNext: 21
D/google_lenve_fb: onNext: 28
D/google_lenve_fb: onNext: 36
D/google_lenve_fb: onNext: 45
D/google_lenve_fb: onNext: 55
D/google_lenve: onNext: 明
D/google_lenve: onNext: 明月
D/google_lenve: onNext: 明月別
D/google_lenve: onNext: 明月別枝
D/google_lenve: onNext: 明月別枝驚
D/google_lenve: onNext: 明月別枝驚鵲

1.6elementAt函數

elementAt函數表示獲取數據源中的第N項數據輸出,以下:

 Observable.just("清", "風", "半", "夜", "鳴", "蟬")
                .elementAt(4)
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve", "onNext: "+s);
                    }
                });

打印結果以下:

D/google_lenve: onNext: 鳴

1.7merge函數

merge函數能夠用來合併多個Observable數據源,而後將合併後的數據在一塊兒輸出,以下:

Observable<String> observable1 = Observable.just("十里樓臺倚翠薇", "百花深處杜鵑啼");
        Observable<String> observable2 = Observable.just("殷勤自與行人語","不似流鶯取次飛");
        Observable.merge(observable1, observable2)
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve", "onNext: "+s);
                    }
                });

打印結果以下:

D/google_lenve: onNext: 十里樓臺倚翠薇
D/google_lenve: onNext: 百花深處杜鵑啼
D/google_lenve: onNext: 殷勤自與行人語
D/google_lenve: onNext: 不似流鶯取次飛

1.8 zip函數

zip函數用來合併多個Observable的數據源,可是與merge不一樣的是,zip函數中能夠對數據源進行二次操做,而不是簡單的合併,代碼以下:

Observable<String> observable1 = Observable.just("十里樓臺倚翠薇", "百花深處杜鵑啼");
        Observable<String> observable2 = Observable.just("問君能有幾多愁","恰似一江春水向東流");
        Observable.zip(observable1, observable2, new Func2<String, String, Object>() {
            @Override
            public Object call(String s, String s2) {
                return s+s2;
            }
        })
        .subscribe(new Subscriber<Object>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Object o) {
                Log.d("google_lenve", "onNext: "+o.toString());
            }
        });

打印日誌以下:

D/google_lenve: onNext: 十里樓臺倚翠薇問君能有幾多愁
D/google_lenve: onNext: 百花深處杜鵑啼恰似一江春水向東流

1.9其餘的過濾函數

Observable函數中還有其餘一些好用的過濾函數,我就再也不一一演示了,小夥伴們看下面的代碼自行試驗便可:

    private void m7() {
        Observable.just(10, 12, 13, 14, 15, 16, 16, 16, 17, 18)
            //在數據序列的開頭插入一條指定的項1
                .startWith(2)
                .filter(new Func1<Integer, Boolean>() {
                    @Override
                    public Boolean call(Integer integer) {
                        return integer > 0;
                    }
                })
            //只發射前N個元素
                .take(2)
            //只發射最後N個元素
                .takeLast(2)
            //只發射第一個元素
                .first()
            //只發射最後一個元素
                .last()
            //跳過前兩個
                .skip(2)
                //跳過最後兩個
                .skipLast(2)
                //數據過濾,過濾掉重複數據
                .distinct()
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.d("google_lenve_fb", "onNext: " + integer);
                    }
                });

1.10 subscribeOn函數和observeOn函數

這兩個函數在咱們Android開發中仍是很是有用的,其中subscribeOn表示指定被觀察者執行的線程,而observeOn則表示觀察者執行的線程,這個解決網絡訪問仍是很是方便的,以下:

Observable<String> observable1 = Observable.just("十里樓臺倚翠薇", "百花深處杜鵑啼");
        Observable<String> observable2 = Observable.just("問君能有幾多愁","恰似一江春水向東流");
        Observable.zip(observable1, observable2, new Func2<String, String, Object>() {
            @Override
            public Object call(String s, String s2) {
                Log.d("google_lenve", "call: "+Thread.currentThread().getName());
                return s+s2;
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<Object>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Object o) {
                Log.d("google_lenve", "onNext: "+Thread.currentThread().getName()+"--------"+o.toString());
            }
        });

打印日誌以下:

D/google_lenve: call: RxCachedThreadScheduler-1
D/google_lenve: call: RxCachedThreadScheduler-1
 D/google_lenve: onNext: main--------十里樓臺倚翠薇問君能有幾多愁
 D/google_lenve: onNext: main--------百花深處杜鵑啼恰似一江春水向東流


2.RxJava在Android中的使用

RxJava在安卓開發中不只可以處理簡單的數據流,最好玩的地方莫過於網絡訪問,我舉一個例子(其餘的數據流處理這裏就再也不介紹了),好比我有一個按鈕,點擊該按鈕加載一張圖片出來,代碼以下:

Observable.create(new Observable.OnSubscribe<Bitmap>() {
            @Override
            public void call(Subscriber<? super Bitmap> subscriber) {
                subscriber.onNext(getBitmap());
            }
        })
                //設置數據加載在子線程進行
                .subscribeOn(Schedulers.io())
                //設置圖片加載在主線程進行
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Bitmap>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Bitmap bitmap) {
                        iv.setImageBitmap(bitmap);
                    }
                });

getBitmap方法以下:

private Bitmap getBitmap() {
        HttpURLConnection con;
        try {
            URL url = new URL("http://img3.cache.netease.com/photo/0008/2016-08-10/BU4A81A72ODN0008.550x.0.jpg");
            con = (HttpURLConnection) url.openConnection();
            con.setConnectTimeout(5 * 1000);
            con.connect();
            if (con.getResponseCode() == 200) {
                return BitmapFactory.decodeStream(con.getInputStream());
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

有沒有感受爽歪歪呢?今後完全告別Handler,告別new Thread。。。。。

3.RxJava配合Retrofit的使用

最後咱們再來看看當下最流行的兩個框架的組合使用!若是你還不瞭解Retrofit的使用,參考我以前的博客一個App帶你學會Retrofit2.0,麻麻不再用擔憂個人網絡請求了!


將RxJava和Retrofit結合的時候,首先先修改gradle文件,先把個人gradle文件拿出來給你們瞧瞧:

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'io.reactivex:rxjava:1.1.0'

APIService中的定義以下:

public interface APIService {
    @GET("api/lore/classify")
    Observable<ClassfyBean> getClassfyBean();
}

建立Retrofit同時建立APIService的實例,代碼以下:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.tngou.net")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        APIService apiService = retrofit.create(APIService.class);

注意,這裏和咱們在通常場景下使用Retrofit有一個區別,那就是多了addCallAdapterFactory這個方法,這裏咱們添加的RxJava的適配工廠。而後咱們就能夠調用APIService中的方法來訪問網絡數據了,以下:

                observable
                //在子線程訪問數據
                .subscribeOn(Schedulers.io())
                //在主線程顯示數據
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<ClassfyBean>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable throwable) {

                    }

                    @Override
                    public void onNext(ClassfyBean classfyBean) {
                        StringBuffer sb = new StringBuffer();
                        for (ClassfyBean.TngouBean tngouBean : classfyBean.getTngou()) {
                            sb.append(tngouBean.getName() + "\n");
                        }
                        tv.setText(sb.toString());
                    }
                });

OK,這纔是網絡訪問和數據處理最佳拍檔。

今天先這樣,後面再找時間詳細介紹這兩個結合的條條框框。。。。


以上。



另外推薦兩篇大神文章:

http://wuxiaolong.me/2016/01/18/rxjava/

http://gank.io/post/560e15be2dca930e00da1083

相關文章
相關標籤/搜索