一. 介紹
RxJava應該說是一種編程框架,采用的模式是觀察者模式。同時它也屬于響應式編程,何為響應式編程?本人建議可以對比流媒體的播放,甚至是cs模式,我理解為一種簡易的問答模式。
需要注意的是觀察者模式是一對多的關系,不難理解,一個觀察者可以觀察很多的角色。因此我大膽的推測,因為是一對多的關系,那么觀察者就不會承擔太多的業(yè)務邏輯和繁瑣的邏輯關系,否則他會被忙死,甚至還有可能導致接受數(shù)據(jù)混亂等不可預知的問題。
推測是否正確,請看下文的原理解說!
二. 原理解說
鑒于本人對部分源碼的分析和demo的編寫,對RxJava我就總結以下三點。
1. 實現(xiàn)
RxJava是一種觀察者模式,如果是第一次聽說這種模式,可以結合EventBus和廣播,甚至可以聯(lián)想到textview的點擊事件來對比想象一下。
所謂觀察者模式,首先得清楚幾個角色,一旦觀察關系產生必然會有所謂的觀察者和被觀察者。顧名思義,觀察者是來監(jiān)視被觀察者的行為,發(fā)現(xiàn)有需要時就采取行動?;氐絼偛诺狞c擊事件,你可以把一個textview當成被觀察者,listener當成觀察者,setOnClickListener是建立兩者關系的產生。講到這你大概可能明白了那么一點。下面就來說說RxJava里面是怎樣產生這種模式的。
首先觀察者是Observer,被觀察者是Observable,訂閱關系是Subscriber。需要說一點的是observer不是狗仔隊不會時時刻刻盯著Observable,相反他很懶很被動,他做的事情只有撒網(wǎng)和收網(wǎng)。即是一開始的訂閱關系建立和接到被觀察者的回調通知。
說多了都會困,明白了這么一點點就先沖擊下視覺,看下面一張關系圖吧。(備注:看圖的時候結合源碼)

圖形解說:先不講解圖,一般來說我們最想知道的一個問題就是:觀察者,被觀察者和訂閱者三者到底是怎么產生關系的,里面終究藏了多少貓膩?
回答:看圖!對于觀察者而言,這簡直就是一尊老佛爺啊,都被動成這個樣子了,他很被動的被強加關系。再看看Observable被觀察者,看著都讓人心疼,掛了多少枝枝葉葉的關系啊。
既然如此,來剝洋蔥吧。首先看這個observer這個觀察者懶貨,為何這么懶,追到源碼里面去:

如此看來懶是有原因的,所謂觀察者就是一個接口包含了三個方法,也證實了我一開始的大膽猜測,觀察者里不會存在太復雜的邏輯。其中核心方法是onNext方法,就是在被觀察者里要觸發(fā)的方法,。

看到上面你會大吃一驚!胡扯!調onNext方法的明明是Subscribler啊,先別發(fā)怒,不懂就要繼續(xù)剝洋蔥,你瞅瞅Subscriber的源碼:


看到這些你還吼嗎?你倒是吼啊?沒錯!subscriber原來是實現(xiàn)了Observer的類,并且多了幾個方法,常用的是onStart方法,取消訂閱和是否已經訂閱,對于這幾個方法我就不多說了,明白人都能看懂。
剝到這一層的時候,正常人的思維都會想到,那被觀察者是不是和Subscriber存在關系?否則觀察關系行不通???嚇得我趕緊去Observable(被觀察者)的源碼證實一下:

艾瑪,打臉了沒找到,不過找到一個很類似的名字(圈紅的類),不到黃河不死心,繼續(xù)剝洋蔥。


終于等到你,還好我沒放棄!妖孽,隱藏的好深!看到這里恍然大悟,一切水落石出了!一句話總結,observable里一直持有subscriber的對象,并且在call方法回調的時候,讓subscriber產生行為。而subscriber盡管改頭換面了一些,但是穿上馬甲龜還是龜,它本身就是對observer的實現(xiàn)。 從表面上看觀察者(observer)懶得無力吐槽,實際上偽裝了一種身份一直潛伏在被觀察者里面。也正因為如此建立一種監(jiān)視的關系,而拋給用戶的只是一開始的兩種訂閱方式:
observable.subscribe(observer);// 是定義的oberver
observable.subscribe(subscriber);// 這個是定義的subscrible
其實,真相都在暗處!上文提到的所謂訂閱關系(subscriber)其實也是觀察者!
2. 異步
Android的多線程可以說是Android的靈魂,而多線程處理不當帶來的坑也是讓大家踩了又踩,我們最怕的就是內存泄漏,而偏偏多線程的處理不當就會造成潛在的風險。
RxJava的異步操作貌似封裝的不錯,至少表面上用起來自己的心里受到了一點點安慰,假裝它內部不存在內存泄漏一說。我們來看看跟平常的handle和aysncTask有啥不一樣的地方。
先拋一張圖:

圖形解說:從圖可看出,線程的調度是被觀察者指定的。通過兩個方法分別指定不同的線程。圖形里面包含兩個調度方法subscribeOn(Schedulers.io())和observeOn(AndroidSchedulers.mainThread()),前者指的是訂閱產生的所在線程,往往是新開啟的線程,這里寫的io是針對于io操作的線程,非io操作的處理最好不要放在此線程里。而后者則是回調所產生的線程,從方法名可以看出觀察者醒了他覺得事都干完了,得處理結果了,而android里面的結果往往是展現(xiàn)在ui上,而ui的更新需要在主線程進行,因此一般回調的時候都會放在主線程操作。
除此之外,圖上還有個關鍵的類Schedulers。這個就是線程的調度類,可以說所有的線程都被這個類操控著。進入源碼可以看到,有三種不同的Schedule,分別是圖中的computationScheduler,ioScheduler和newThreadScheduler。至于他三個的區(qū)別參考下面:
1. computationScheduler
特點:計算所使用的Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作,例如圖形的計算。這個Scheduler使用的固定的線程池,大小為 CPU 核數(shù)。不要把 I/O 操作放在computation()中,否則 I/O 操作的等待時間會浪費 CPU。
實現(xiàn):
Scheduler c = RxJavaPlugins.getInstance().getSchedulersHook().getComputationScheduler();
if(c !=null) {
computationScheduler= c;
}else{
computationScheduler=newEventLoopsScheduler();
}
2. ioScheduler
特點:I/O 操作(讀寫文件、讀寫數(shù)據(jù)庫、網(wǎng)絡信息交互等)所使用的Scheduler。行為模式和newThread()差不多,區(qū)別在于io()的內部實現(xiàn)是是用一個無數(shù)量上限的線程池,可以重用空閑的線程,因此多數(shù)情況下io()比newThread()更有效率。不要把計算工作放在io()中,可以避免創(chuàng)建不必要的線程。
實現(xiàn):
Scheduler io = RxJavaPlugins.getInstance().getSchedulersHook().getIOScheduler();
if(io !=null) {
ioScheduler= io;
}else{
ioScheduler=newCachedThreadScheduler();
}
3. newThreadScheduler
特點:總是啟用新線程,并在新線程執(zhí)行操作。
實現(xiàn):
Scheduler io = RxJavaPlugins.getInstance().getSchedulersHook().getIOScheduler();
if(io !=null) {
ioScheduler= io;
}else{
ioScheduler=newCachedThreadScheduler();
}
實例:

總結:
異步的內部實現(xiàn)機制以newThreadSchedule為例其實是實現(xiàn)了Executor最終還是實現(xiàn)了runnable,但是對開發(fā)者而言不僅邏輯明了簡單,使用起來也是很簡單,從一定意義上來講不見了到處使用handler的影子。
3. 對象靈活轉換
說到這,大家都會想到map和flatmap。關于這兩個東東網(wǎng)上有很多介紹,但是你會發(fā)現(xiàn)介紹的越仔細,你會越懵逼。那就跟著我的思路,我?guī)忝攵?/p>
第一步,先看源碼:
map核心源碼:

flatmap核心源碼:

lift源碼:

說明:為什么我要強調這三個方法?對,你猜對了!因為我們扒進去一看,最終都跟這個lift有關系。既然都跟這個有關系,那就進去看看這個到底實現(xiàn)了什么玩意兒。尼瑪!一堆泛型,先不管這些玩意,映入眼簾的是熟悉的Observable和熟悉的Subscriber。好!有這兩個就夠了!
仔細一看其實也沒什么特比之處嘛,就是和正常的使用一樣在被觀察者里面調用call通知觀察者。如此簡單而已!不,等等!怎么還有一句:onSubscribe.call(st);哦哦,問題來了,很多同學看到此處可能有點懵逼了。再仔細看一下 Observable也是new出來的,感情這兩玩意都是新的啊。不錯!就是新的!
第二部,實例:
例如,我有個用戶實體類,但是類里面還有其他的子類。
第一個需求,我想得到用戶實體

第二個需求,我想得到每一個用戶實體的每一個子類的信息(說的那么繞,其實簡單來講就是類里面套類,我通常喜歡稱之為類里面對應一個列表)

第三步,大白話總結:
看到以上兩步,你可能還是沒咋看的明白,覺得我?guī)銈兠攵谴蹬?。但是接下來的大白話絕對讓你心服口服!再沒講大土話之前,我順便提一句,RxJava在很多同學眼里受青睞的一個最重要的原因就是多變,所謂多變比如在map里面我new一個func1任意指定你的類型,call都會給我返回你想要的類型。其實,懂得人都明白為什么可以實現(xiàn)這樣呢?進去Func1你會發(fā)現(xiàn)這個接口里面定義的call方法的返回值也是泛型??傊畞碚f,之所以能多變就是因為它啥啥都支持泛型。
言歸正傳,該說說重點了!flit里面的正真實現(xiàn)和android事件分發(fā)幾乎一毛一樣,簡而言之就是處理一件事的路徑很深的話我就不想自己搞下去了,要么是因為懶要么是因為官大裝逼,反正我看到本次操作完成不了我就開始分發(fā),也可以稱之為代理。總之遵循只處理一個層級的原則,因此就會看到有新的observable和subscriber產生??傊痪湓挘琭lit里面做到事情就是任務層層的派發(fā),并且每一次調度這個方法都會產生新的觀察者,可以理解為很多個代理在做同一件事,我再次大膽的猜測這樣就會提高執(zhí)行的效率,反正事多兵也多。 (這句話只是猜測,沒有證實,有興趣的朋友可以去研究下,通過時間的分析)
三.使用
使用很簡單,在gradle里面添加如下兩句:
compile'io.reactivex:rxjava:1.0.14'
compile'io.reactivex:rxandroid:1.0.1'
然后就是寫你的觀察者--observer和被觀察者observable以及兩者產生的訂閱關系。
四.總結
RXjava是一種使用起來簡單,并且支持lambda表達式,很受同學們喜歡。還能很好的和retrift結合使用,尤其是對多線程的處理,可以說是既簡單又好理解。
總之,以上也僅僅十個人的學習總結,有不當之處還望指出,期待和你共同成長!