這篇博文醞釀很久了,今天終於下定決心開始寫!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,廢話很少說,那就開始吧!編程
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); } });
onNext: 哈哈哈哈 onNext: lalalala onCompleted: onCompleted()
@Override public void onNext(String s) { Log.d("google_lenve_fb", "onNext: " + s); int i = 1 / 0; }
onNext: 哈哈哈哈 onError:onError()
在實際開發中,咱們的數據來源多是多種多樣的,爲了簡化數據操做,Observable類爲咱們提供了許多現成的方法,這些方法都可以極大的簡化咱們對數據的操做,一個一個來看吧。
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); } });
D/google_lenve_fb: onNext: 竹外桃花三兩枝 D/google_lenve_fb: onNext: 春江水暖鴨先知
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: 濁酒一杯家萬里
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: 夢迴吹角連營---辛棄疾
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: 秋水共長天一色李廣難封
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: 明月別枝驚鵲
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: 鳴
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: 不似流鶯取次飛
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: 百花深處杜鵑啼恰似一江春水向東流
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); } });
這兩個函數在咱們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--------百花深處杜鵑啼恰似一江春水向東流
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); } });
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; }
最後咱們再來看看當下最流行的兩個框架的組合使用!若是你還不瞭解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'
public interface APIService { @GET("api/lore/classify") Observable<ClassfyBean> getClassfyBean(); }
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://www.tngou.net") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); APIService apiService = retrofit.create(APIService.class);
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()); } });
今天先這樣,後面再找時間詳細介紹這兩個結合的條條框框。。。。
以上。
另外推薦兩篇大神文章:
http://wuxiaolong.me/2016/01/18/rxjava/
http://gank.io/post/560e15be2dca930e00da1083