序言:蝸殼已經(jīng)退役一年多了,但是還是抵不住蝸殼在NBA界的影響力,最近NBA流行向“蝸殼挑戰(zhàn)”瘫寝,事情起源于蝸殼給IT和北境之王設(shè)定了新賽季的挑戰(zhàn)爵政,然后眾多球星也紛紛向蝸殼討要挑戰(zhàn)。作為蝸殼的忠實(shí)球迷钢悲,作為一個(gè)IT黨点额,雖說(shuō)向蝸殼也討不到挑戰(zhàn),但是自己還是要對(duì)自己有一個(gè)挑戰(zhàn)的莺琳。
1还棱、RxJava是一個(gè)使用可觀測(cè)的序列來(lái)組成異步的、基于事件的程序的庫(kù)惭等。其特點(diǎn)是異步珍手,觀察者模式。
2、觀察者模式中的觀察者和被觀察者之間的關(guān)系是一對(duì)多琳要,即多個(gè)觀察者可以觀察同一個(gè)被觀察者對(duì)象寡具,在RxJava2中,Observable稱(chēng)之為“被觀察者”稚补,Observer稱(chēng)之為“觀察者”童叠。
3、RxJava2中創(chuàng)建Observable的方式有很多種孔厉,具體如下所示:
(1)拯钻、create()方法:
Observable.create(ObservableOnSubscribe<T> source)
,此種方法是Observable最基本的創(chuàng)建方式撰豺》喟悖可以看到,這里傳入了一個(gè) ObservableOnSubscribe對(duì)象作為參數(shù)污桦,它的作用相當(dāng)于一個(gè)計(jì)劃表亩歹,當(dāng) Observable被訂閱的時(shí)候,ObservableOnSubscribe的subscribe()方法會(huì)自動(dòng)被調(diào)用凡橱,事件序列就會(huì)依照設(shè)定依次觸發(fā)(對(duì)于上面的代碼小作,就是觀察者Observer 將會(huì)被調(diào)用一次 onNext())。這樣稼钩,由被觀察者調(diào)用了觀察者的回調(diào)方法顾稀,就實(shí)現(xiàn)了由被觀察者向觀察者的事件傳遞,即觀察者模式坝撑。(2)静秆、just()方法:
Observable.just(T item)
,使用just()巡李,將為你創(chuàng)建一個(gè)Observable并自動(dòng)為你調(diào)用onNext()發(fā)射數(shù)據(jù)抚笔。通過(guò)just()方式直接觸發(fā)onNext(),just中傳遞的參數(shù)將直接在Observer的onNext()方法中接收到侨拦。(3)殊橙、fromArray()方法:
Observable.fromArray(T... items)
,使用fromArray()狱从,該方法的使用以及效果與just()方法是一樣的膨蛮,與just()方法的區(qū)別在于該方法參數(shù)是不限的,而just()方法參數(shù)個(gè)數(shù)是有限的(4)季研、fromIterable()方法:
Observable.fromIterable(Iterable<? extends T> source)
敞葛,使用fromIterable(),遍歷集合训貌,發(fā)送每個(gè)item。相當(dāng)于多次回調(diào)onNext()方法,每次傳入一個(gè)item递沪。注意:Collection接口是Iterable接口的子接口豺鼻,所以所有Collection接口的實(shí)現(xiàn)類(lèi)都可以作為Iterable對(duì)象直接傳入fromIterable()方法。(5)款慨、interval()方法:
Observable.interval(long period, TimeUnit unit)
儒飒,Observable.interval(long initialDelay, long period, TimeUnit unit)
,創(chuàng)建一個(gè)按固定時(shí)間間隔發(fā)射整數(shù)序列的Observable檩奠,可用作定時(shí)器桩了。即按照固定period時(shí)間調(diào)用一次onNext()方法。默認(rèn)從0開(kāi)始埠戳,也可以自己設(shè)置開(kāi)始值(initialDelay)井誉。(6)、range()方法:
Observable.range(final int start, final int count)
整胃,創(chuàng)建一個(gè)發(fā)射特定整數(shù)序列的Observable颗圣,第一個(gè)參數(shù)為起始值,第二個(gè)為發(fā)送的個(gè)數(shù)屁使,如果為0則不發(fā)送在岂,負(fù)數(shù)則拋異常。上述表示發(fā)射start到count的數(shù)蛮寂。即調(diào)用count次nNext()方法蔽午,依次傳入start-count之間的數(shù)字。
當(dāng)然了酬蹋,還有很多其他的方式創(chuàng)建Observable及老,這里就不一一舉例了:
3、在RxJava中除嘹,有很多的操作符写半,不同的操作符都有不同的用處,以下列舉幾個(gè)比較常用的操作符:
(1)尉咕、map()操作符:
map(Function<? super T, ? extends R> mapper)
叠蝇,map操作符的作用就是將原始的Observable對(duì)象轉(zhuǎn)換成另一個(gè)Observable對(duì)象,同時(shí)將傳輸?shù)臄?shù)據(jù)進(jìn)行一些靈活的操作年缎,方便Observer獲得想要的數(shù)據(jù)格式進(jìn)行后續(xù)的操作悔捶。(2)、flatmap()操作符:
flatmap(Function<? super T, ? extends ObservableSource<? extends R>> mapper)
单芜,flatMap()對(duì)于數(shù)據(jù)的轉(zhuǎn)換比map()更加徹底蜕该,如果發(fā)送的數(shù)據(jù)是集合,flatMap()重新生成一個(gè)Observable對(duì)象洲鸠,并把數(shù)據(jù)轉(zhuǎn)換成Observer想要的數(shù)據(jù)形式堂淡。它可以返回任何它想返回的Observable對(duì)象馋缅。flatMap的另一作用就是加工Observable。(3)绢淀、filter()操作符:
filter(Predicate<? super T> predicate)
萤悴,filter是用于過(guò)濾數(shù)據(jù)的,該方法的返回值是一個(gè)boolean類(lèi)型皆的,返回false表示攔截此數(shù)據(jù)不再發(fā)送覆履,返回true則繼續(xù)發(fā)送。(4)费薄、take()操作符:
take(long count)
硝全,take用于發(fā)射被觀察者的前count個(gè)item。(5)楞抡、distinct()操作符:
distinct()
伟众,distinct操作符的作用是去除重復(fù)的觀察者,一般我們用來(lái)對(duì)數(shù)據(jù)進(jìn)行去重操作拌倍。(6)赂鲤、delay()操作符:
delay(long delay, TimeUnit unit)
,delay操作符的作用就是延時(shí)發(fā)射Observable里面的事件柱恤,經(jīng)過(guò)delay的時(shí)間才會(huì)收到Observable發(fā)出的事件数初。(7)、reduce操作符:
reduce(BiFunction<T, T, T> reducer)
梗顺,reduce操作符可以把一個(gè)被觀察者中的多個(gè)事件進(jìn)行壓縮泡孩,最后發(fā)射壓縮后的事件。我們可以使用reduce操作符做一個(gè)疊加操作活著疊減操作寺谤。
4仑鸥、RxJava最大的一個(gè)特點(diǎn)就是異步,所以當(dāng)然少不了和線程打交道了变屁,RxJava中有一個(gè)線程調(diào)度器Scheduler眼俊,以下列舉幾種常用的線程模式:
(1)、Schedulers.newThread():總是啟用新線程粟关,并在新線程執(zhí)行操作疮胖,因此它可以創(chuàng)建無(wú)限量的工作線程。
(2)闷板、Schedulers.trampoline():主要用于延遲工作任務(wù)的執(zhí)行澎灸。當(dāng)我們想在當(dāng)前線程執(zhí)行一個(gè)任務(wù)時(shí),并不是立即遮晚,trampoline的操作是FIFO隊(duì)列操作性昭,我們可以用trampoline()將它入隊(duì)。trampoline將會(huì)處理它的隊(duì)列并且按序運(yùn)行隊(duì)列中每一個(gè)任務(wù)县遣。
(3)糜颠、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)建不必要的線程法绵。
(4)、AndroidSchedulers.mainThread():這是Android特有的線程酪碘,UI主線程朋譬。
通過(guò)上述幾種線程控制,我們就能實(shí)現(xiàn)異步操作了兴垦,subscribeOn(): 指定Observable(被觀察者)所在的線程徙赢,或者叫做事件產(chǎn)生的線程。observeOn(): 指定Observer(觀察者)所運(yùn)行在的線程探越,或者叫做事件消費(fèi)的線程狡赐。
5、RxJava的觀察者能收到三種事件钦幔,onNext(基本事件)枕屉,onComplete(完成事件),onError(異常事件)鲤氢。被觀察者可以發(fā)送無(wú)限個(gè)onNext事件搀擂,但是只能發(fā)送一個(gè)onComplete或者onError事件,觀察者也可以接收無(wú)限個(gè)onNext事件卷玉,也只能接收一個(gè)onComplete或者onError事件哨颂,為什么這里說(shuō)或者呢,因?yàn)閛nComplete事件和onError事件屬于互斥事件相种,二者只能出現(xiàn)其一威恼,而且當(dāng)這兩個(gè)事件被發(fā)送或者接收之后就不能再發(fā)送事件和接收事件了。
6蚂子、Rxjava中沃测,還有一個(gè)很大的變化就是Backpressure(背壓),何為背壓食茎,就是觀察者來(lái)不及處理被觀察者發(fā)出的事件(產(chǎn)生事件的速度大于處理事件的速度)蒂破,導(dǎo)致事件被無(wú)限堆積,最后產(chǎn)生異常别渔。在2.0版本中有一個(gè)專(zhuān)門(mén)針對(duì)背壓的被觀察者Flowable附迷,分別有以下幾種策略:
(1)惧互、ERROR策略:在異步調(diào)用時(shí),RxJava中有個(gè)緩存池喇伯,用來(lái)緩觀察者處理不了暫時(shí)緩存下來(lái)的數(shù)據(jù)喊儡,緩存池的默認(rèn)大小為128,即只能緩存128個(gè)事件稻据“拢回調(diào)的時(shí)候會(huì)傳給我們一個(gè)Subscription對(duì)象,調(diào)用該對(duì)象的
request(long n)
方法可以向被觀察者申請(qǐng)消費(fèi)的事件數(shù)捻悯,調(diào)用該對(duì)象的cancel()
方法也可以切斷被觀察者和觀察者之間的聯(lián)系匆赃,這一點(diǎn)和Disposable一樣。無(wú)論request()中傳入的數(shù)字比128大或小今缚,緩存池中在剛開(kāi)始都會(huì)存入128個(gè)事件算柳。當(dāng)然如果本身并沒(méi)有這么多事件需要發(fā)送,則不會(huì)存128個(gè)事件姓言。在ERROR策略下瞬项,如果緩存池溢出,就會(huì)立刻拋出MissingBackpressureException異常何荚。(2)囱淋、BUFFER策略:剛才我們說(shuō)到RxJava中有個(gè)緩存池,默認(rèn)的大小是只能緩存128個(gè)事件餐塘,BUFFER策略就是將這個(gè)緩存池變大绎橘,即緩存的事件會(huì)更多。因此這種策略比較耗內(nèi)存唠倦,會(huì)導(dǎo)致OOM称鳞,所以不推薦使用。
(3)稠鼻、DROP策略:當(dāng)觀察者處理不了事件冈止,就丟棄。觀察者通過(guò)request()傳入其需求n候齿,然后被觀察者把n個(gè)事件傳遞給觀察者供其消費(fèi)熙暴。其他消費(fèi)不掉的事件就丟掉。
(4)慌盯、LATEST策略:LATEST與DROP功能基本一致周霉。唯一的區(qū)別就是LATEST總能使觀察者能夠接收到被觀察者產(chǎn)生的最后一個(gè)事件。
參考:手把手教你使用 RxJava 2.0系列
相關(guān)代碼已上傳至GitHub傳送門(mén)