淺談Rxjava

最近項目中用到了異步操作,感覺android自身的AsyncTask和handler有點繁瑣且不夠簡潔,于是學習了一下Rxjava,并沒有特別深入,但有了基本的了解

一.簡介

RxJava 在 GitHub 主頁上的自我介紹是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一個在 Java VM 上使用可觀測的序列來組成異步的、基于事件的程序的庫)。

RxJava 的優(yōu)勢就是簡潔,但它的簡潔的與眾不同之處在于,隨著程序邏輯變得越來越復雜,它依然能夠保持簡潔。其原理在于,RxJava 的實現(xiàn),是一條從上到下的鏈式調(diào)用,沒有任何嵌套,這在邏輯的簡潔性上是具有優(yōu)勢的。當需求變得復雜時,這種優(yōu)勢將更加明顯。

二.基本概念

Observable:發(fā)射源,英文釋義“可觀察的”,在觀察者模式中稱為“被觀察者”或“可觀察對象”;

Observer:接收源,英文釋義“觀察者”,沒錯!就是觀察者模式中的“觀察者”,可接收Observable、Subject發(fā)射的數(shù)據(jù);

Subscriber:“訂閱者”,也是接收源,那它跟Observer有什么區(qū)別呢?Subscriber實現(xiàn)了Observer接口,比Observer多了一個最重要的方法unsubscribe( ),用來取消訂閱,當你不再想接收數(shù)據(jù)了,可以調(diào)用unsubscribe( )方法停止接收,Observer 在 subscribe() 過程中,最終也會被轉換成 Subscriber 對象,一般情況下,建議使用Subscriber作為接收源;

Subscription :Observable調(diào)用subscribe( )方法返回的對象,同樣有unsubscribe( )方法,可以用來取消訂閱事件;

Action0:RxJava中的一個接口,它只有一個無參call()方法,且無返回值,同樣還有Action1,Action2...Action9等,Action1封裝了含有 1 個參的call()方法,即call(T t),Action2封裝了含有 2 個參數(shù)的call方法,即call(T1 t1,T2 t2),以此類推;

Func0:與Action0非常相似,也有call()方法,但是它是有返回值的,同樣也有Func0、Func1...Func9;

RxJava 的觀察者模式大致如下圖:

image.png

與傳統(tǒng)觀察者模式不同, RxJava 的事件回調(diào)方法除了普通事件 onNext() (相當于 onClick() / onEvent())之外,還定義了兩個特殊的事件:onCompleted() 和 onError()。

  • onCompleted(): 事件隊列完結。RxJava 不僅把每個事件單獨處理,還會把它們看做一個隊列。RxJava 規(guī)定,當不會再有新的 onNext() 發(fā)出時,需要觸發(fā) onCompleted() 方法作為標志。
  • onError(): 事件隊列異常。在事件處理過程中出異常時,onError() 會被觸發(fā),同時隊列自動終止,不允許再有事件發(fā)出。
  • 在一個正確運行的事件序列中, onCompleted() 和 onError() 有且只有一個,并且是事件序列中的最后一個。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在隊列中調(diào)用了其中一個,就不應該再調(diào)用另一個。

三.基本用法

  • 創(chuàng)建 Observer
Observer<String> observer = new Observer<String>() {
    @Override
    public void onNext(String s) {
        Log.d(tag, "Item: " + s);
    }

    @Override
    public void onCompleted() {
        Log.d(tag, "Completed!");
    }

    @Override
    public void onError(Throwable e) {
        Log.d(tag, "Error!");
    }
};```

- **創(chuàng)建 Observable**
1.使用create( )

Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello");
subscriber.onCompleted();
}
});```
可以看到,這里傳入了一個 OnSubscribe 對象作為參數(shù)。OnSubscribe 會被存儲在返回的 Observable 對象中,它的作用相當于一個計劃表,當 Observable 被訂閱的時候,OnSubscribe 的 call() 方法會自動被調(diào)用,事件序列就會依照設定依次觸發(fā)(對于上面的代碼,就是觀察者Subscriber 將會被調(diào)用一次 onNext() 和一次 onCompleted())。這樣,由被觀察者調(diào)用了觀察者的回調(diào)方法,就實現(xiàn)了由被觀察者向觀察者的事件傳遞,即觀察者模式。

2.使用just( ),將為你創(chuàng)建一個Observable并自動為你調(diào)用onNext( )發(fā)射數(shù)據(jù):

justObservable = Observable.just("just1","just2");//依次發(fā)送"just1"和"just2"```
  3.使用from( ),遍歷集合,發(fā)送每個item:

List<String> list = new ArrayList<>();
list.add("from1");
list.add("from2");
list.add("from3");
fromObservable = Observable.from(list); //遍歷list 每次發(fā)送一個
/** 注意,just()方法也可以傳list,但是發(fā)送的是整個list對象,而from()發(fā)送的是list的一個item** /```

  • Subscribe (訂閱)
observable.subscribe(observer);

Observer的onNext方法將會依次收到來自justObservable的數(shù)據(jù),另外,如果你不在意數(shù)據(jù)是否接收完或者是否出現(xiàn)錯誤,即不需要Observer的onCompleted()和onError()方法,可使用Action1,subscribe()支持將Action1作為參數(shù)傳入,RxJava將會調(diào)用它的call方法來接收數(shù)據(jù),代碼如下:

justObservable.subscribe(new Action1<String>() {
    @Override
    public void call(String s) {

          ...
     }});```
- **線程控制 —— Scheduler **
在不指定線程的情況下, RxJava 遵循的是線程不變的原則,即:在哪個線程調(diào)用 subscribe(),就在哪個線程生產(chǎn)事件;在哪個線程生產(chǎn)事件,就在哪個線程消費事件。如果需要切換線程,就需要用到 Scheduler (調(diào)度器)。

  RxJava 已經(jīng)內(nèi)置了幾個 Scheduler ,它們已經(jīng)適合大多數(shù)的使用場景:

  - Schedulers.immediate(): 直接在當前線程運行,相當于不指定線程。這是默認的 Scheduler。
 - Schedulers.newThread(): 總是啟用新線程,并在新線程執(zhí)行操作。
 - Schedulers.io(): I/O 操作(讀寫文件、讀寫數(shù)據(jù)庫、網(wǎng)絡信息交互等)所使用的 Scheduler。行為模式和 newThread() 差不多,區(qū)別在于 io() 的內(nèi)部實現(xiàn)是是用一個無數(shù)量上限的線程池,可以重用空閑的線程,因此多數(shù)情況下 io() 比 newThread() 更有效率。不要把計算工作放在 io() 中,可以避免創(chuàng)建不必要的線程。
  - Schedulers.computation(): 計算所使用的 Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作,例如圖形的計算。這個 Scheduler 使用的固定的線程池,大小為 CPU 核數(shù)。不要把 I/O 操作放在 computation() 中,否則 I/O 操作的等待時間會浪費 CPU。
  - Schedulers.mainThread(),它指定的操作將在 Android 主線程運行。

  有了這幾個 Scheduler ,就可以使用 subscribeOn() 和 observeOn() 兩個方法來對線程進行控制了。 subscribeOn(): 指定 subscribe() 所發(fā)生的線程,即 Observable.OnSubscribe 被激活時所處的線程。或者叫做事件產(chǎn)生的線程。 observeOn(): 指定 Subscriber 所運行在的線程。或者叫做事件消費的線程。

  比如說:
Observable.just(1, 2, 3, 4)
.subscribeOn(Schedulers.io()) // 指定 subscribe() 發(fā)生在 IO 線程
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回調(diào)發(fā)生在主線程
.subscribe(new Action1<Integer>() {
    @Override
    public void call(Integer number) {
        
    }
});```

上面這段代碼中,由于 subscribeOn(Schedulers.io()) 的指定,被創(chuàng)建的事件的內(nèi)容 1、2、3、4 將會在 IO 線程發(fā)出;而由于observeOn(AndroidScheculers.mainThread()) 的指定,因此 subscriber 數(shù)字的打印將發(fā)生在主線程 。事實上,這種在 subscribe() 之前寫上兩句 subscribeOn(Scheduler.io()) 和 observeOn(AndroidSchedulers.mainThread()) 的使用方式非常常見,它適用于多數(shù)的 『后臺線程取數(shù)據(jù),主線程顯示』的程序策略。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內(nèi)容