【RxJava】- 變換操作符源碼分析

【RxJava】- 創建操作符源碼分析
【RxJava】- 過濾操作符源碼分析
【RxJava】- 結合操作符源碼分析
【RxJava】- 連接操作符源碼分析

注意

文章中說的被觀察者和觀察者可以看------RxJava的基本執行流程。比如Observable.create傳入的參數是被觀察者,而subscribe傳入的參數是觀察者,因為前者是事件的發射地,而后者是接收事件的地方,事件發射地的變化,我們都能第一時間得知,就好像我們在觀察前者一樣。

Compose

通過對其應用特定操作。比如在網絡請求中,需要在觀察者接收通知前對返回的數據做一定的處理后,再通知觀察者。

FlatMap

FlatMap將一個發射數據的Observable變換為多個Observables,然后將它們發射的數據合并后放進一個單獨的Observable。

FlatMap功能由

ObservableFlatMap
ObservableMapNotification
ObservableInternalHelper
FlatMapWithCombinerOuter
ObservableFlatMapCompletableCompletable
ObservableFlattenIterable
FlatMapIntoIterable
ObservableFlatMapMaybe
ObservableFlatMapSingle

實現

ObservableFlatMap

首先調用ObservableFlatMap的subscribeActual方法,并觀察者實例。

public void subscribeActual(Observer<? super U> t) {
    if (ObservableScalarXMap.tryScalarXMapSubscribe(source, t, mapper)){return;}
     source.subscribe(new MergeObserver<>(t, mapper, delayErrors, maxConcurrency, bufferSize));
}
tryScalarXMapSubscribe方法

如果被觀察者(比如Observable.create傳入的參數)是Supplier類型,返回true。

直接調用Supplier的get方法獲取事件數據,然后調用FlatMap傳入的數據轉換包裝實例的apply方法,得到一個包裝后,類型為ObservableSource的c。

如果得到的數據包裝實例也是Supplier類型,者直接調用Supplier的get方法獲取新的數據,新數據可以被轉換,也可以沒有轉換。然后調用觀察者的onSubscribe方法,緊接著調用觀察者的onNext,onComplete等方法。

如果得到的數據包裝實例不是Supplier類型,這直接調用數據包裝實例的subscribe方法,并把觀察者實例傳過去。這樣,可以由數據包裝實例對數據轉換后自己給觀察者發出通知。

source.subscribe(new MergeObserver<>(t, mapper, delayErrors, maxConcurrency, bufferSize))

調用被觀察者subscribe方法,傳入MergeObserver實例,看上去是不是像是又創建了一個新的被觀察者和觀察者關系。在觀察者subscribe里實現事件發射邏輯,在MergeObserver接收事件。下面重點看一下onNext方法。

  • onNext
    首先獲取數據包裝實例,如果數據個數大于最大允許的個數,將不在往隊列里面插入,直接返回。

  • subscribeInner
    如果數據包裝實例是Supplier類型,者從隊列取出數據包裝實例,調用Supplier的get方法獲取新的轉換數據,然后通知觀察者。

    如果不是Supplier類型,創建InnerObserver實例,傳入上面創建的MergeObserver實例,添加到,然后調用數據包裝實例的subscribe方法,就好像數據包裝實例做被觀察者,InnerObserver作為觀察者。發射的數據會被保存在InnerObserver中的隊列queue中,然后一一發射給觀察者。queue是線程可見的隊列,這樣可以運用到多線程中。

    RxJava很多操作符都對多線程進行了支持和處理,如果想在多線程中使用,可以自己查看一下源碼。也不是很難。

ObservableMapNotification

這個類大概就是通過傳入的數據包裝實例對數據做轉換,然后通知觀察者,具體邏輯可以自己查看源碼,源碼很少很簡單。

FlatMapWithCombinerOuter

簡單看了一下代碼,大概功能是,將得到的兩個包裝數據實例進行合并,前一個包裝數據實例會被傳入到第二包裝實例里面,然后返回最終的包裝數據。

當有兩個數據需要合并成一個新的數據實例時,可以用這個。

ObservableFlatMapCompletableCompletable

將值序列映射到CompletableSources中,并等待其終止。代碼不多,自己查看。

ObservableFlattenIterable

將序列映射為Iterable并發出其值。然后遍歷迭代器發射數據。

flatMapIntoIterable

功能和ObservableFlattenIterable差不多,只是被觀察者本身就是一個迭代器。

ObservableFlatMapMaybe

將上游值映射到MaybeSources中,并將其信號合并為一個序列。

ObservableFlatMapSingle

將上游值映射到SingleSources并將其信號合并為一個序列。

GroupBy

將一個Observable分拆為一些Observables集合,它們中的每一個發射原始Observable的一個子序列,GroupBy操作符將原始Observable分拆為一些Observables集合,它們中的每一個發射原始Observable數據序列的一個子序列。哪個數據項由哪一個Observable發射是由一個函數判定的,這個函數給每一項指定一個Key,Key相同的數據會被同一個Observable發射。

只有ObservableGroupBy實現類。在ObservableGroupBy維護著 groups(Map<Object, GroupedUnicast<K, V>>)這樣一個數組,當發射數據是,首先獲取key,然后從groups獲取key對應的GroupedUnicast實例,GroupedUnicast中有 State<T, K> state實例,而state維護著queue(SpscLinkedArrayQueue)數組來存放發射的數據。

group.onNext(v);

if (newGroup) {
   downstream.onNext(group);
   if (group.state.tryAbandon()) {
       cancel(key);
       group.onComplete();
   }
}

如果不是新創建的GroupedUnicast實例,那么可以推斷直接已經發射過,所以在GroupedUnicast中已經存在觀察者實例。如果是新創建的,執行downstream.onNext(group)。進入后面的流程。

GroupJoin

由ObservableGroupBy實現。將不同數據來源的數據進行合并,合并規則自己查看源碼。

Map

由ObservableMap實現。對Observable發射的每一項數據應用一個函數,執行變換操作。就相當于FlatMap中的獲取包裝數據,然后直接通知觀察者。源碼很簡單,自己查看。

Scan

實現類有

ObservableScan
ObservableScanSeed

連續地對數據序列的每一項應用一個函數,然后連續發射結果。Scan操作符對原始Observable發射的第一項數據應用一個函數,然后將那個函數的結果作為自己的第一項數據發射。它將函數的結果同第二項數據一起填充給這個函數來產生它自己的第二項數據。它持續進行這個過程來產生剩余的數據序列。這個操作符在某些情況下被叫做accumulator。

源碼很簡單,自己查看。

Window

這個就帶大家分析源碼了,有興趣的可以自己查看,如果只是想知道用法,請參考Window

總結

其實網上有很多對RxJava操作符的講解,還有對官網文檔的翻譯,我覺得,要想對RxJava用好,還是要自己去查看源碼。其實RxJava雖然很多,但是每個操作符都有獨立的實現,分析源碼其實也不難。只要你了解了被觀察者和觀察者的調用關系,很多操作符只不過是在中間有添加了被觀察者和觀察者過程。相當于嵌套。如果你了解這個執行過程,你可以很快找到關鍵的執行代碼。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • ReactiveX 系列文章目錄 buffer 間隔固定個數緩存 按照規定大小緩存,每次取 count 個數,取完...
    三流之路閱讀 1,272評論 0 1
  • 記錄RxJava操作符,方便查詢(2.2.2版本) 英文文檔地址:http://reactivex.io/docu...
    凌云飛魚閱讀 835評論 0 0
  • 一、RxJava操作符概述 RxJava中的操作符就是為了提供函數式的特性,函數式最大的好處就是使得數據處理簡潔易...
    測天測地測空氣閱讀 647評論 0 1
  • 創建操作 用于創建Observable的操作符Create通過調用觀察者的方法從頭創建一個ObservableEm...
    rkua閱讀 1,863評論 0 1
  • 今天,對RxJava中的變換操作符進行學習。 一、變換操作符的作用 對事件序列中的事件/整個事件序列進行加工處理(...
    Jotyy閱讀 248評論 0 0