Rxjava 基礎(chǔ)原理之總結(jié)

簡(jiǎn)述:

a library for composing asynchronous and event-based programs using obaservable for the
Java VM (一個(gè)對(duì)于構(gòu)成使用的Java虛擬機(jī)觀察序列號(hào)異步和基于事件的程序庫(kù))碰辅。

總結(jié):隨著程序邏輯變得越來(lái)越復(fù)雜寺晌,它依然能夠保持簡(jiǎn)潔。

RxJava引入的目的:異步,代碼更清晰

優(yōu)點(diǎn):采用觀察者模式鏈?zhǔn)秸{(diào)用,簡(jiǎn)潔明了,以往實(shí)現(xiàn)子線(xiàn)程主線(xiàn)程切換需自己手動(dòng)new Thread(推送線(xiàn)程池)柴信,
并且線(xiàn)程之間還需要使用handler進(jìn)行通信,Rxjava一步到位宽气,極其簡(jiǎn)單随常。

1.基礎(chǔ)概念:

Observable(?b?z?:v?bl):在觀察者模式中稱(chēng)為“被觀察者”

Observer(?b?z?:v?(r)):觀察者模式中的“觀察者”潜沦,可接收Observeable發(fā)送的數(shù)據(jù)

subscribe(s?b?skra?b):訂閱,觀察者與被觀察者绪氛,通過(guò)subscribe()方法進(jìn)行訂閱

subscriber(s?b?skra?b?(r)):也是一種觀察者唆鸡,在2.0中它與Observer沒(méi)什么實(shí)質(zhì)的區(qū)別,不同的是Subscriber與Flowable聯(lián)合使用

Flowable(f'la??bl):也是悲觀餐者的一種枣察,與Subscriber進(jìn)行配合使用争占,實(shí)現(xiàn)背壓操作

RxJava的異步實(shí)現(xiàn)方式:
    讓Observable開(kāi)啟子線(xiàn)程執(zhí)行耗時(shí)操作,完成耗時(shí)操作后序目,觸發(fā)回調(diào)臂痕,通知Observer進(jìn)行主線(xiàn)程UI更新。
    如此輕松便可以實(shí)現(xiàn)Android中的異步猿涨,且代碼簡(jiǎn)潔明了刻蟹,集中分布。
    RxJava中默認(rèn)Observer和Observable都在同一線(xiàn)程執(zhí)行任務(wù)嘿辟。

RxJava的使用Action

2.Rxjava常用操作符

from()操作符:

接受數(shù)組或集合,返回一個(gè)按參數(shù)列表順序發(fā)射這些數(shù)據(jù)的Observable片效。
源碼:
public final static <T> Observable<T> from(Iterable<? extents T> iterable){
    return create(new OnSubscribeFromIterable<T>(iterable));
}
例如:
String[] array = {"Amy","Rookie","MLXG"};
Observable.from(array)
    .subscribe(new Observer<String>(){
        ...
    });

just()操作符:

接受1-9個(gè)參數(shù)红伦,它們還可以是不同類(lèi)型,返回一個(gè)按參數(shù)列表順序發(fā)射這些數(shù)據(jù)的Observable淀衣。
例如:
    Observable.just(1,2.4,"adb")
        .subscribe(new Action1<String>(){
            ...
        });

map()操作符:

把原來(lái)的Observable對(duì)象轉(zhuǎn)換成另一個(gè)Observable對(duì)象昙读,方便Observer獲得想要的數(shù)據(jù)形式,一對(duì)一 
列如:
    Observable.just("images/logo.png")              //輸入類(lèi)型 String
        .map(new Func1<String,Bitmap>(){
            @Verride
            public Bitmap call(String filePath){    //參數(shù)類(lèi)型 String
                return getBitmapFromPath(filePath); //返回類(lèi)型 Bitmap
            }
        })
        .subscribe(new Action1<Bitmap>(){
            @Override
            public void call(Bitmap bitmap){        //參數(shù)類(lèi)型 bitmap
                showBitmap(bitmap)
            }
        });

flatMap()操作符:

返回任何它想返回的Observable對(duì)象膨桥,一對(duì)多 
列如:
    Student[] students = ...?;
    Subscriber<Course> subscriber = new Subscriber<Course>(){
        @Override
        public void onNext(Course course){
            ...
        }
    };
    Observable.from(students)
        .flatMap(new Func1<Student,Observable<Course>>() {
            @Override
            public Observable<Course> call(Student student) {
                return Observable.from(student.getCourses());
            }
    })
    .subscribe(subscriber);

filter()操作符:

Func中對(duì)每項(xiàng)元素進(jìn)行過(guò)濾處理蛮浑,滿(mǎn)足條件的元素才會(huì)繼續(xù)發(fā)送,下面的過(guò)濾偶數(shù)只嚣。
列如:
    Observable.just(2,3,23,54,15)
        .filter(new Func1<Integer,Boolean>() {
            @Override
            public Boolean call(Integer integer){
                return integer % 2 == 0;
            }
        })
        .subscribe(new Observer<Integer>(){
            @Override
            public void onNext(Integer integer){
                ...
            }
            ...
        });

take()操作符:

輸出最多指定數(shù)量的結(jié)果
列如:
    Observable.just(1,2,3,4)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .take(3)    //只發(fā)送前三個(gè)事件 
        ...

doOnNext()操作符:

用來(lái)在觀察者Observer.onNext()方法調(diào)用之前進(jìn)行一些初始化操作沮稚,保存/緩存網(wǎng)絡(luò)結(jié)果
例如:
    Observable.just(1,2,3)
        .doOnNext(new Action1<Integer>(){
            @Override
            public void call(Integer integer){
                ...
            }
        })
        ...

Merge()操作符:

合并多個(gè)Observable,按照加入的Observable順序?qū)⒏鱾€(gè)元素傳遞册舞。
例如:
    Observable<Integer> obserable1 = Observable.just(2,12,34,32);
    Observable<Integer> obserable2 = Observable.just(32,12,43,2);
    Observable.merge(observable1,observable2)
            .subscribe(new Observer<Integer>(){
        ...
    });

zip()操作符:

將各個(gè)Observable個(gè)對(duì)應(yīng)位置各個(gè)元素取出做操作蕴掏,然后將結(jié)果傳遞。
例如:
    Observable<Integer> observable1 = Observable.just(1,2,3);
    Observable<Integer> observable2 = Observable.just(11,22);
    Observable.zip(observable1,observable2,newFunc2<Integer,Integer,Integer>(){
        @Override
        public Integer call(Integer integer1,Integer integer){
            return integer1+integer2;
        }   
    })
    .subscribe(new Observable<Integer>(){
        ...
        @Override
        public void onNext(Integer integer){
            //out 12调鲸、24盛杰、3
        }
    });

3.Scheduler(調(diào)度號(hào))切換線(xiàn)程

Schedulers.immediate(): 
    直接在當(dāng)前線(xiàn)程運(yùn)行,相當(dāng)于不指定線(xiàn)程藐石,默認(rèn)

Schedulers.newThread():
    總是啟動(dòng)新線(xiàn)程即供,并在新線(xiàn)程操作

Schedulers.io():
    用于IO密集型任務(wù),如異步阻塞IO操作于微,這個(gè)調(diào)度器的線(xiàn)程池會(huì)根據(jù)需要增長(zhǎng)逗嫡;
    對(duì)于普通的計(jì)算任務(wù)青自,請(qǐng)使用Schedulers.computation();
    Schedulers.io()默認(rèn)是一個(gè)CachedThreadScheduler,很像一個(gè)有線(xiàn)程緩存的新線(xiàn)程調(diào)度器。

Schedulers.computation():
    用于計(jì)算任務(wù)祸穷,如事件循環(huán)或和回調(diào)處理性穿,不要用于IO操作(IO操作請(qǐng)使用Schedulers.io());默認(rèn)線(xiàn)程數(shù)等于處理器的數(shù)量       
Schedulers.trampoline():
    當(dāng)其它排隊(duì)的任務(wù)完成后,在當(dāng)前線(xiàn)程排隊(duì)開(kāi)始執(zhí)行雷滚。

SubscribeOn\ObserveOn

subscribeOn():
    指定Observable(被觀察者)所在的線(xiàn)程需曾,或叫做事件產(chǎn)生的線(xiàn)程。
observeOn():
    指定Observer(觀察者)所運(yùn)行在的線(xiàn)程祈远,或叫做事件消費(fèi)的線(xiàn)程呆万。

4.Fowable與Subscriber

當(dāng)被觀察者發(fā)射數(shù)據(jù)的速度大于觀察者接收處理數(shù)據(jù)的速度,造成觀察者的調(diào)度器中數(shù)據(jù)緩沖池?zé)o限堆積车份,
超出了緩沖池的最大容量谋减,導(dǎo)致OOM.
例如:
Observable.create(new ObservableOnSubscribe<String>(){
        @Override
        public void subscribe(ObservableEmitter<String> e) throws Exception{
            int a = 0;
            while(true){
                e.onNext("data:"+(i++));
            }
        }
    }).subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())  
        .subscribe(new Consumer<String>(){
            @Override
            public void accept(String s) throws Exception{
            Thread.sleep(2000);
            print(s);
        }
    });

而此時(shí)Flowable的背壓策略就很好的解決這個(gè)問(wèn)題.
例如:

    Flowable.create(new FlowableOnSubscribe<String>(){
            @Override
            public void subcribe(@NonNull FlowableEmitter<String> e) throws Exception{
                int i = 0;
                while(true){
                    e.onNext("data:"+(i++));
                }
            }
        },BackpressureStrategy.DROP)    //超出緩沖池的數(shù)據(jù)丟棄
            .subecribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<String>(){
                Subscription subscription;
                @Override
                public void onSubsrcibe(Subscription s){
                    subscription = s;
                    subscription.request(1);
                }
                @Override
                public void onNext(String s){
                    try{
                        Thread.sleep(2000);
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                    printThred(2);
                    subscription.request(1);    //處理完了扫沼,再請(qǐng)求數(shù)據(jù)
                }
                
                ...
        });

該背壓策略是超出緩沖池的數(shù)據(jù)被丟棄出爹,而觀察者要求處理一個(gè) 發(fā)送我一個(gè)數(shù)據(jù)。

Backpressure的策略

a.被觀察者和觀察者在異步線(xiàn)程的情況下缎除,如果被觀察者發(fā)射事件的速度大于
  觀察者接收事件的速度严就,就會(huì)產(chǎn)生Backpressure問(wèn)題。
  但是同步情況下器罐,Backpressure問(wèn)題不會(huì)存在梢为。

b.Backpressure的策略?xún)H僅是調(diào)度Subscriber接收事件,并不影響Flowable
  發(fā)送事件轰坊。觀察者可以根據(jù)自身實(shí)際情況按需拉取數(shù)據(jù)铸董,而不是被動(dòng)接收。
  最終實(shí)現(xiàn)了上游被觀察者發(fā)送事件的速度的控制肴沫,實(shí)現(xiàn)了背壓的策略粟害。

c.Backpressure的策略有5種:ERROR,BUFFER,DROP,LATEST,MISSING

ERROR:

用來(lái)緩存觀察者處理不了暫時(shí)緩存下來(lái)的數(shù)據(jù),緩沖池的默認(rèn)大小為128樊零,即只能緩存128個(gè)事件我磁。
如果緩沖池溢出,就會(huì)立刻拋出MissingBackpressureException異常驻襟。

BUFFER:

即把默認(rèn)容器為128的緩存池成一個(gè)大的緩存池夺艰,支持很多的數(shù)據(jù),這種方式
比較消耗內(nèi)存沉衣。

DROP:

當(dāng)消費(fèi)者處理不了的時(shí)候就丟棄郁副,消費(fèi)者通過(guò)request傳入其需求n(事件個(gè)數(shù)),
然后生產(chǎn)著把n個(gè)事件傳遞給消費(fèi)者供其消費(fèi)豌习,其他消費(fèi)不掉的丟棄存谎。

LATEST:

基本和DROP一致拔疚,消費(fèi)者通過(guò)request傳入需求n,然后生產(chǎn)者把n個(gè)事
件傳遞給消費(fèi)者供其消費(fèi),其他消費(fèi)不掉的事件就丟棄既荚。
唯一區(qū)別是LATEST總能使消費(fèi)者能夠接收到生產(chǎn)者產(chǎn)生的最好一個(gè)事件稚失。

MISSING:

沒(méi)有緩沖池,接收第一個(gè)數(shù)據(jù)之后恰聘,后面的都丟棄句各。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晴叨,隨后出現(xiàn)的幾起案子凿宾,更是在濱河造成了極大的恐慌,老刑警劉巖兼蕊,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件初厚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡孙技,警方通過(guò)查閱死者的電腦和手機(jī)产禾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)牵啦,“玉大人下愈,你說(shuō)我怎么就攤上這事±倬茫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵拌夏,是天一觀的道長(zhǎng)僧著。 經(jīng)常有香客問(wèn)我,道長(zhǎng)障簿,這世上最難降的妖魔是什么盹愚? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮站故,結(jié)果婚禮上皆怕,老公的妹妹穿的比我還像新娘。我一直安慰自己西篓,他們只是感情好愈腾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著岂津,像睡著了一般虱黄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吮成,一...
    開(kāi)封第一講書(shū)人閱讀 51,488評(píng)論 1 302
  • 那天橱乱,我揣著相機(jī)與錄音辜梳,去河邊找鬼。 笑死泳叠,一個(gè)胖子當(dāng)著我的面吹牛作瞄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播危纫,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼宗挥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了叶摄?” 一聲冷哼從身側(cè)響起属韧,我...
    開(kāi)封第一講書(shū)人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蛤吓,沒(méi)想到半個(gè)月后宵喂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡会傲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年锅棕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淌山。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡裸燎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泼疑,到底是詐尸還是另有隱情德绿,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布退渗,位于F島的核電站移稳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏会油。R本人自食惡果不足惜个粱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望翻翩。 院中可真熱鬧都许,春花似錦、人聲如沸嫂冻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)桨仿。三九已至弧烤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背暇昂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工莺戒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人急波。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓从铲,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親澄暮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子名段,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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

  • 在正文開(kāi)始之前的最后,放上GitHub鏈接和引入依賴(lài)的gradle代碼: Github: https://gith...
    蘇蘇說(shuō)zz閱讀 678評(píng)論 0 2
  • 轉(zhuǎn)一篇文章 原地址:http://gank.io/post/560e15be2dca930e00da1083 前言...
    jack_hong閱讀 915評(píng)論 0 2
  • 前言我從去年開(kāi)始使用 RxJava 泣懊,到現(xiàn)在一年多了伸辟。今年加入了 Flipboard 后,看到 Flipboard...
    占導(dǎo)zqq閱讀 9,164評(píng)論 6 151
  • 一馍刮、Retrofit詳解 ·Retrofit的官網(wǎng)地址為 : http://square.github.io/re...
    余生_d630閱讀 1,856評(píng)論 0 5
  • 《異類(lèi)》的作者是馬爾科姆格拉德威爾信夫,《引爆點(diǎn)》也是出自他之手。 《異》這本書(shū)想講一個(gè)道理——成功人士的成功卡啰,很大程...
    英子Lucy閱讀 229評(píng)論 0 0