RxJava學(xué)習(xí)筆記

參閱
給 Android 開(kāi)發(fā)者的 RxJava 詳解
什么是函數(shù)式編程
RxJava 2.0 全新來(lái)襲
基于RxJava 1.x,結(jié)合RxJava 2.0整理學(xué)習(xí)筆記含滴。

概念

1.實(shí)現(xiàn)了異步操作的庫(kù)溶弟;
2.通過(guò)擴(kuò)展觀察者模式來(lái)實(shí)現(xiàn)異步沙廉;

Observable發(fā)送消息扶叉,而Subscriber則用于消費(fèi)消息。
與觀察者不同的是逼裆,Observable一般只有等到有Subscriber通過(guò)subscribe方法訂閱它郁稍,才會(huì)開(kāi)始發(fā)送消息。

基礎(chǔ)類(lèi)/方法

  • ** Observer(觀察者)**胜宇,接口耀怜。
    它決定事件觸發(fā)的時(shí)候?qū)⒂性鯓拥男袨椤?br> 定義了4個(gè)行為/方法: onSubscribe(), onNext(), onError(), onComplete(),
/**
 * 創(chuàng)建一個(gè)觀察者
 */
Observer<String> observer = new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {
    }
    @Override
    public void onNext(String s) {
    }
    @Override
    public void onError(Throwable e) {
    }
    @Override
    public void onComplete() {
    }
};
  • Subscriber(訂閱者),接口桐愉。等價(jià)于觀察者财破。與觀察者不同之處在于:onSubscribe方法的參數(shù)不同,而且兩者位于不同的jar包下从诲。
    Subscriber位于reactive-streams.jar文件下左痢,包名:org.reactivestreams.Subscriber
    Observable位于rxjava.jar文件下,包名:io.reactivex.Observable
/**
 * 創(chuàng)建一個(gè)訂閱者
 */
Subscriber<String> subscriber = new Subscriber<String>() {

    @Override
    public void onSubscribe(Subscription s) {

    }

    @Override
    public void onNext(String s) {

    }

    @Override
    public void onError(Throwable t) {

    }

    @Override
    public void onComplete() {

    }
};
  • Observable (被觀察者)系洛,抽象類(lèi)
    它決定什么時(shí)候觸發(fā)事件以及觸發(fā)怎樣的事件
  /**
 * 創(chuàng)建一個(gè)Observable對(duì)象俊性,并定義事件處理規(guī)則。當(dāng)它被訂閱的時(shí)候描扯,事件會(huì)按順序依次觸發(fā)定页。
 */
Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
        emitter.onNext("Hello");
        emitter.onNext("Hi");
        emitter.onNext("Aloha");
        emitter.onComplete();
    }
});

create()方法是 RxJava 最基本的創(chuàng)造事件序列的方法≌莱希基于這個(gè)方法典徊, RxJava 還提供了一些方法用來(lái)快捷創(chuàng)建事件隊(duì)列。
例如:

  • just(T ...)


    just方法
  • fromArray(T... items)

    Observable observable1 = Observable.just("Hello", "Hi", "Aloha");
    Observable observable2 = Observable.fromArray("Hello", "Hi", "Aloha");
    
  • Flowable(被觀察者)恩够,抽象類(lèi)卒落。等價(jià)于Observable。RxJava 2.x引入蜂桶。

RxJava1.x中儡毕,Observeable用于訂閱Observer和Subscriber。

RxJava2.x中扑媚, Observeable用于訂閱Observer 腰湾,是不支持背壓的贾费,而 Flowable用于訂閱Subscriber ,是支持背壓(Backpressure)的檐盟。

背壓是指在異步場(chǎng)景中,被觀察者發(fā)送事件速度遠(yuǎn)快于觀察者的處理速度的情況下押桃,一種告訴上游的被觀察者降低發(fā)送速度的策略 葵萎,在1.0中,關(guān)于背壓最大的遺憾唱凯,就是集中在Observable這個(gè)類(lèi)中羡忘,導(dǎo)致有的Observable支持背壓,有的不支持磕昼。為了解決這種缺憾卷雕,新版本把支持背壓和不支持背壓的Observable區(qū)分開(kāi)來(lái)。

  • subscribe(訂閱)票从,方法漫雕。
訂閱方法
observable.subscribe(observer);
//RxJava 2.x中如下方法編譯報(bào)錯(cuò),沒(méi)有提供與Subscriber對(duì)象關(guān)聯(lián)的方法
//observable1.subscribe(subscriber);

可以從上圖的訂閱方法中發(fā)現(xiàn)Consumer類(lèi)峰鄙。

  • Consumer(消費(fèi)者)浸间, 一個(gè)接口。用于接受單個(gè)值吟榴。
Consumer onNextConsumer = new Consumer<String>() {
    @Override
    public void accept(@NonNull String o) throws Exception {

    }
};

Consumer onErrorConsumer = new Consumer<String>() {
    @Override
    public void accept(@NonNull String o) throws Exception {

    }
};

observable.subscribe(onNextConsumer, onErrorConsumer);

顯然魁蒜,subscribe方法支持不完整定義的回調(diào),可以根據(jù)需求單獨(dú)處理只需要的回調(diào)吩翻,而無(wú)需每次都處理Observer中的4個(gè)回調(diào)兜看。Consumer可以定義Observer的每一個(gè)部分,Observable.subscribe()函數(shù)能夠處理一個(gè)狭瞎,兩個(gè)细移、三個(gè)或者4個(gè)參數(shù),分別表示onNext()脚作,onError()葫哗,onComplete()和onSubscribe函數(shù)。響應(yīng)順序是onSubscribe->onNext->onComplete或者onError球涛。

范例

  1. 將字符串?dāng)?shù)組 names 中的所有字符串依次打印出來(lái):
String[] names = {"Jason", "Bob", "Coco"};
Observable.fromArray(names).subscribe(new Consumer<String>() {
    @Override
    public void accept(@NonNull String s) throws Exception {
        System.out.println("name:" + s);
    }
});
  1. 由 id 取得圖片并顯示
Observable.create(new ObservableOnSubscribe<Drawable>() {
    @Override
    public void subscribe(ObservableEmitter<Drawable> e) throws Exception {
        //根據(jù)id獲取Drawable對(duì)象劣针,回調(diào)到觀察者中。
        Drawable drawable = getResources().getDrawable(R.drawable.ic_action_name);
        e.onNext(drawable);
        e.onComplete();
    }
}).subscribe(new Consumer<Drawable>() {
    @Override
    public void accept(@NonNull Drawable drawable) throws Exception {
        ImageView imageView = (ImageView) findViewById(R.id.image);
        imageView.setImageDrawable(drawable);
    }
}, new Consumer<Throwable>() {
    @Override
    public void accept(@NonNull Throwable throwable) throws Exception {
        System.out.println(throwable.getMessage());
    }
});

在 RxJava 的默認(rèn)規(guī)則中亿扁,事件的發(fā)出和消費(fèi)都是在同一個(gè)線程的捺典。也就是說(shuō),如果只用上面的方法从祝,實(shí)現(xiàn)出來(lái)的只是一個(gè)同步的觀察者模式襟己。觀察者模式本身的目的就是『后臺(tái)處理引谜,前臺(tái)回調(diào)』的異步機(jī)制,因此異步對(duì)于 RxJava 是至關(guān)重要的擎浴。而要實(shí)現(xiàn)異步员咽,則需要用到 RxJava 的另一個(gè)概念: Scheduler 。

線程控制

  • Scheduler(調(diào)度器)贮预,抽象類(lèi)
  • Scheduler的子類(lèi)有ComputationScheduler贝室、ExecutorScheduler、ImmediateThinScheduler仿吞、NewThreadScheduler滑频、SingleScheduler、TrampolineScheduler唤冈。
  • Schedulers 一個(gè)可以返回標(biāo)準(zhǔn)Scheduler實(shí)例的靜態(tài)工廠峡迷。


    方法
    • Schedulers.newThread(): 為每個(gè)工作單元?jiǎng)?chuàng)建一個(gè)新的線程。
    • Schedulers.io(): I/O 操作(讀寫(xiě)文件你虹、讀寫(xiě)數(shù)據(jù)庫(kù)绘搞、網(wǎng)絡(luò)信息交互等)所使用的 Scheduler。
      與newThread()的區(qū)別在于 io() 的內(nèi)部實(shí)現(xiàn)是是用一個(gè)無(wú)數(shù)量上限的線程池傅物,可以重用空閑的線程看杭,因此多數(shù)情況下 io() 比 newThread() 更有效率。
      不要把計(jì)算工作放在 io() 中挟伙,可以避免創(chuàng)建不必要的線程楼雹,計(jì)算工作可以使用computation()方法。
    • Schedulers.computation(): 用于計(jì)算型工作例如事件循環(huán)和回調(diào)處理尖阔。
      這個(gè)計(jì)算指的是 CPU 密集型計(jì)算贮缅,即不會(huì)被 I/O 等操作限制性能的操作,例如圖形的計(jì)算介却。
      這個(gè) Scheduler 使用的固定的線程池谴供,大小為 CPU 核數(shù)。
      不要把 I/O 操作放在 computation() 中齿坷,否則 I/O 操作的等待時(shí)間會(huì)浪費(fèi) CPU桂肌。
    • Schedulers.single(): 單線程,共享的Scheduler永淌。
  • Schedulers.trampoline():在當(dāng)前線程上工作崎场,但不立即執(zhí)行的Scheduler。
    在當(dāng)前線程中的工作放入隊(duì)列中排隊(duì)遂蛀,并依次操作谭跨。
  • 另外, Android 還有一個(gè)專(zhuān)用的 AndroidSchedulers.mainThread(),它指定的操作將在 Android 主線程運(yùn)行螃宙。

使用 subscribeOn() 和 observeOn() 兩個(gè)方法來(lái)對(duì)線程進(jìn)行控制了蛮瞄。前者
用于指定被觀察者執(zhí)行的線程,或者叫事件產(chǎn)生的線程谆扎。后者用于指定觀察者執(zhí)行的線程挂捅,或者叫事件消費(fèi)的線程。

Observable.create(new ObservableOnSubscribe<Drawable>() {
    @Override
    public void subscribe(ObservableEmitter<Drawable> e) throws Exception {
        //根據(jù)id獲取Drawable對(duì)象堂湖,回調(diào)到觀察者中籍凝。
        Drawable drawable = getResources().getDrawable(R.drawable.ic_action_name);
        e.onNext(drawable);
        e.onComplete();
    }
})
.subscribeOn(Schedulers.io())//用于指定被觀察者執(zhí)行的線程
.observeOn(AndroidSchedulers.mainThread())//用于執(zhí)行觀察者執(zhí)行的線程
.subscribe(new Consumer<Drawable>() {
    @Override
    public void accept(@NonNull Drawable drawable) throws Exception {
        ImageView imageView = (ImageView) findViewById(R.id.image);
        imageView.setImageDrawable(drawable);
    }
}, new Consumer<Throwable>() {
    @Override
    public void accept(@NonNull Throwable throwable) throws Exception {
        System.out.println(throwable.getMessage());
    }
});

變換

所謂變換,就是將事件序列中的對(duì)象或整個(gè)序列進(jìn)行加工處理苗缩,轉(zhuǎn)換成不同的事件或事件序列。

篇幅較長(zhǎng)声诸,請(qǐng)參閱給 Android 開(kāi)發(fā)者的 RxJava 詳解酱讶。

簡(jiǎn)單的說(shuō)就是在發(fā)送者Observable和消息消費(fèi)者Subscriber之間對(duì)消息進(jìn)行各種你所需要的加工處理。
RxJava(一)基礎(chǔ)知識(shí)
RxJava(二) Operator

關(guān)鍵方法

  • map()
  • flatMap()

其他觀察者模式

當(dāng)然彼乌,除了上面這兩種觀察者泻肯,還有一類(lèi)觀察者
Single/SingleObserver
Completable/CompletableObserver
Maybe/MaybeObserver

更多請(qǐng)參閱RxJava 2.0 全新來(lái)襲

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市慰照,隨后出現(xiàn)的幾起案子灶挟,更是在濱河造成了極大的恐慌,老刑警劉巖毒租,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稚铣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡墅垮,警方通過(guò)查閱死者的電腦和手機(jī)惕医,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)算色,“玉大人抬伺,你說(shuō)我怎么就攤上這事≡置危” “怎么了峡钓?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)若河。 經(jīng)常有香客問(wèn)我能岩,道長(zhǎng),這世上最難降的妖魔是什么萧福? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任捧灰,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘毛俏。我一直安慰自己炭庙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布煌寇。 她就那樣靜靜地躺著焕蹄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪阀溶。 梳的紋絲不亂的頭發(fā)上腻脏,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音银锻,去河邊找鬼永品。 笑死,一個(gè)胖子當(dāng)著我的面吹牛击纬,可吹牛的內(nèi)容都是我干的鼎姐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼更振,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼炕桨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起肯腕,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤献宫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后实撒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體姊途,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年知态,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吭净。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肴甸,死狀恐怖寂殉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情原在,我是刑警寧澤友扰,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站庶柿,受9級(jí)特大地震影響村怪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜浮庐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一甚负、第九天 我趴在偏房一處隱蔽的房頂上張望柬焕。 院中可真熱鬧,春花似錦梭域、人聲如沸斑举。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)富玷。三九已至,卻和暖如春既穆,著一層夾襖步出監(jiān)牢的瞬間赎懦,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工幻工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留励两,地道東北人拳芙。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓棺亭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親犯建。 傳聞我的和親對(duì)象是個(gè)殘疾皇子迁酸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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