原文連接:RxAndroid Basics: Part 1java
若是你在閱讀這篇文章,相信你必定很想了解RxJava以及如何在Android應用中使用它。可能你已經見過RxJava的代碼了,但仍然有些疑惑,願你能在這篇文章裏找到答案。android
當我第一次使用RxJava的時候我只是在照搬代碼,這些代碼能跑起來,可是我對RxJava的基礎部分仍然存在誤解,並且我找不到好的源碼來學習。因此爲了理解RxJava,我不得不一點一點學習,踩了很多坑。git
爲了避免讓你把我踩過的坑再踩一遍,我會基於個人學習成果寫一些例子出來,目的就是讓你可以對RxJava有足夠的瞭解,並能在你的Android應用中使用它。github
源碼能夠在這裏找到。在每一個例子的開始,我會寫清每一個代碼段是屬於哪一個Activity的。我會將本文分爲兩個部分,在第一部分裏,我會着重講解如何用RxJava異步加載數據;在第二部分裏,我會探索一些更高級的用法。網絡
在開始說代碼以前,先澄清幾個概念。RxJava最核心的東西就是Observable和Observer。Observable會發出數據,而與之相對的Observer則會經過訂閱Observable來進行觀察。多線程
Observer能夠在Observable發出數據、報錯或者聲明沒有數據能夠發送時進行相應的操做。這三個操做被封裝在Observer接口中,相應的方法爲onNext(),onError()和onCompleted()。app
明確了這些概念之後,讓咱們來看一些例子。異步
如今要寫一個用來展現一個顏色列表的Activity。咱們要寫一個能發送一個字符串列表、而後結束的Observeable。然後咱們會經過這個字符串列表來填充顏色列表,這裏要使用到Observable.just()方法。由這個方法建立的Observable對象的特色是:全部Observer一旦訂閱這個Observable就會當即調用onNext()方法並傳入Observable.just()的參數,然後由於Observable沒有數據能夠發送了,onComplete()方法會被調用。ide
Observable<List<String>> listObservable = Observable.just(getColorList());
注意這裏的getColorList()是一個不耗時的方法。雖然如今看來這個方法無足輕重,但一會咱們會回到這個方法。學習
下一步,咱們寫一個Observer來觀察Observable。
listObservable.subscribe(new Observer<List<String>>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(List<String> colors) { mSimpleStringAdapter.setStrings(colors); } });
然後神奇的事情就發生了。如我剛纔所說,一旦經過subscribe()方法訂閱Observable,就會發生一系列事情:
請記住:經過Observable被訂閱後的行爲來區分它們。
在這個例子中咱們不關心Observable什麼時候完成數據的傳輸,因此咱們不用在onComplete()方法裏寫代碼。並且在這裏不會有異常拋出,因此咱們也不用管onError()方法。
寫了這麼多你可能以爲不少餘,畢竟咱們本能夠在adapter中直接設置做爲數據源的顏色列表。請帶着這個疑問,和我看下面這個更有趣一些的例子。
在這裏咱們要寫一個顯示電視劇列表的Activity。在Android中RxJava的主要用途就在於異步數據加載。首先讓咱們寫一個Observable:
Observable<List<String>> tvShowObservable = Observable.fromCallable(new Callable<List<String>>() { @Override public List<String> call() { return mRestClient.getFavoriteTvShows(); } });
在剛纔的例子中,咱們使用Observable.just()來建立Observable,你可能認爲在這裏能夠經過Observable.just(mRestClient.getFavoriteTvShows())來建立Observable。
但在這裏咱們不能這麼作,由於mRestClient.getFavoriteTvShows()會發起網絡請求。若是在這裏咱們使用Observable.just(),mRestClient.getFavoriteTvShows()會被當即執行並阻塞UI線程。
使用Observable.fromCallable()方法有兩點好處:
這兩點好處有時可能很是重要。如今讓咱們訂閱這個Observable。
mTvShowSubscription = tvShowObservable .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<List<String>>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(List<String> tvShows){ displayTvShows(tvShows); } });
讓咱們一個方法一個方法地來看這段代碼。subscribeOn會修改咱們剛剛建立的Observable。在默認狀況下Observable的全部代碼,包括剛纔說到的只有在被訂閱以後纔會執行的代碼,都會在執行subscribe()方法的線程中運行。而經過subscribeOn()方法,這些代碼能夠在其餘線程中執行。但具體是哪一個線程呢?
在這個例子中咱們讓代碼在"IO Scheduler"中執行(Schedulers.io())。如今咱們能夠只把Scheduler當作一個能夠工做的子線程,這個描述對於如今的咱們已經足夠了,不過這其中還有更深層次的內容。
不過咱們的確遇到了一個小障礙。既然Observable會在IO Scheduler中運行,那麼它與Observer的鏈接也會在IO Scheduler中完成。這就意味着Observer的onNext()方法也會在IO Scheduler中運行,而onNext()方法會操做UI中的View,但View只能在UI主線程中操做。
事實上解決這個問題也很簡單,咱們能夠告訴RxJava咱們要在UI線程中觀察這個Observable,也就是,咱們想讓onNext()方法在UI線程中執行。這一點咱們能夠經過在observeOn()方法中指定另外一個Scheduler來完成,在這裏也就是AndroidSchedules.mainThread()所返回的Scheduler(UI線程的Scheduler)。
然後咱們調用subscribe()方法。這個方法最重要,由於Callable只會在有Observer訂閱後運行。還記得剛纔我說Observable經過其被訂閱後的行爲來區分嗎?這就是一個很好的例子。
還有最後一件事。這個mTvShowSubscription究竟是什麼?每當Observer訂閱Observable時就會生成一個Subscription對象。一個Subscription表明了一個Observer與Observable之間的鏈接。有時咱們須要操做這個鏈接,這裏拿在Activity的onDestroy()方法中的代碼舉個例子:
if (mTvShowSubscription != null && !mTvShowSubscription.isUnsubscribed()) { mTvShowSubscription.unsubscribe(); }
若是你與多線程打過交道,你確定會意識到一個大坑:當Activity執行onDestroy()後線程才結束(甚至永不結束)的話,就有可能發生內存泄漏與NullPointerException空指針異常。
Subscription就能夠解決這個問題,咱們能夠經過調用unsubscribe()方法告訴Observable它所發送的數據再也不被Observer所接收。在調用unsubscribe()方法後,咱們建立的Observer就再也不會收到數據了,同時也就解決了剛纔說的問題。
說到這裏難點已通過去,讓咱們來總結一下:
此次咱們仍是寫一個展現電視劇列表的Activity,但此次咱們走一種更簡單的風格。Observable挺好用的,但在某些狀況下過於重量級。好比說,你可能一經發如今過去的兩個方法中咱們只是讓Observable發送一個數據,並且咱們歷來也沒寫過onComplete()回調方法。
其實呢,Observable還有一個精簡版,叫作Single。Single幾乎和Observable如出一轍,但其回調方法不是onComplete()/onNext()/onError(),而是onSuccess()/onError()。
咱們如今把剛纔寫過的Observable用Single重寫一遍。首先咱們要建立一個Single:
Single<List<String>> tvShowSingle = Single.fromCallable(new Callable<List<String>>() { @Override public List<String> call() throws Exception { mRestClient.getFavoriteTvShows(); } });
而後訂閱一下:
mTvShowSubscription = tvShowSingle .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new SingleSubscriber<List<String>>() { @Override public void onSuccess(List<String> tvShows) { displayTvShows(tvShows); } @Override public void onError(Throwable error) { displayErrorMessage(); } });
這段代碼和剛纔很像,咱們調用subscribeOn()方法以確保getFavoriteTvShows()在子線程中執行。然後咱們調用observeOn()以確保Single的數據被髮送到UI線程。
但此次咱們再也不使用Observer,而是使用一個叫SingleSubscriber的類。這個類和Observer很是像,只不過它只有上述兩個方法:onSuccess()和onError()。SingleSubscriber之於Single就如Observer之於Observable。
訂閱一個Single的同時也會自動建立一個Subscription對象。這裏的Subscription和案例2中沒有區別,必定要在onDestroy()中解除訂閱。
最後一點:在這裏咱們添加了處理異常的代碼,因此若是mRestClient出了問題,onError()就會被調用。建議你親手寫一個案例玩一玩,體驗一下有異常時程序是怎麼運行的。