Rxjava原始碼思路分析與程式設計師的思考

wutongke發表於2017-03-04

Rxjava近來在技術圈非常火,個人認為其優勢主要是兩點:

  • 執行緒切換
    使用Rxjava 可以非常方便指定訂閱者對執行執行緒,這一點對於安卓開發中來說簡直美妙
  • 邏輯清晰
    使用Rxjava自帶的幾個函式對資料進行處理, 程式碼可以非常整齊,邏輯很清晰。

java作為一個靜態語言,缺少了很多靈活性,使用起來很多時候感覺非常死板,使用Rxjava後其類似函式式語言的特性讓人感覺很靈動。本文主要來分析一下Rxjava原始碼是如何將這樣一個個複雜的流程清晰地展現出來的。

先來看一下一個Rxjava使用的一個例子:

Observable.just("a", "b", "c", "d")
                .observeOn(Schedulers.computation())
                .map(new Func1<String, String>() {
                    @Override
                    public String call(String s) {
                        System.out.print(Thread.currentThread().getName() + ":first--" + s);
                        return s + s;
                    }
                })
                .observeOn(Schedulers.io())
                .map(new Func1<String, String>() {
                    @Override
                    public String call(String s) {
                        System.out.print(Thread.currentThread().getName() + ":second--" + s);
                        return s + s;
                    }
                })
                .observeOn(Schedulers.newThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        System.out.print(Thread.currentThread().getName());
                        System.out.print("completed");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.print("error");
                    }

                    @Override
                    public void onNext(String s) {
                        System.out.println(s);
                    }
                });複製程式碼

這是一個非常簡單的流程,但是也進行了三次執行緒的切換,對原始資料進行了兩次map,可以看到使用Rxjava非常優雅,邏輯也很清楚。以下來通過該過程對Rxjava的邏輯進行一些分析。

關鍵類

首先來介紹一下原始碼中的幾個重要的類:

  1. Observable
    Observable是使用Rxjava的入口,很多重要的方法都在此類中,如常用的create(), map(), filter(), subscribe()等。

  2. OnSubscribe
    OnSubscribe是Observable中定義的介面,繼承自Action1介面,實際只有一個call方法,但是Rxjava流程中多個環節中的多個類都實現了該介面,之後通過連結串列到方式連線起來。

  3. Operator
    Operator是Observable中定義的介面,繼承自Func1介面,在Rxjava中需要切換執行緒的時候均需要實現該介面,java中不能直接傳遞函式,所以只能通過介面的方式來實現。
  4. ObserveOnSubseriber
    ObserveOnSubseriber是OperatorObserveOn類中的靜態類,它是資料處理的關鍵,該類繼承自Subscriber類,實現基本的onNext,onError, onCompleate方法。
  5. Worker
    Worker是Scheduler中的一個抽象靜態類,worker是真正執行任務的地方,在worker中含有各個執行緒池的引用,在這裡進行執行緒的執行。

Rxjava流程

Rxjava流程實際上時一個連結串列結構,程式碼例子每一個"."在具體實現中都建立了一個Observable物件,然後通過parent或者source屬性連線起來,當subscibe方法執行後,通過一個list連線各個subscriber,通過連結串列回溯到最開始的地方,然後從最開始處理資料,資料再一級一級傳遞,直到所有資料處理完成。
下邊以一個簡單的流程示意一下,可能不太準確,但是原理差不多:

  • 連結串列建立:A(just)-B(lift(執行緒切換實際是通過lift實現))-C(map)-D(lift)-(map)
  • subscribe開始執行程式碼
  • 通過回溯連結串列建立subscriber list
  • 回溯到資料來源,開始通過fun對資料進行處理,資料處理通過建立的subscriber list不斷傳輸處理,直到最終的subsciber執行完成。

實際基本過程進行了三遍。

以下是一張根據實際原始碼繪製的流程圖,理解原理後結合圖就可以愉快地看原始碼了:

Rxjava原始碼思路分析與程式設計師的思考
Paste_Image.png

可以根據順序標號走一遍流程,基本原始碼也就理解一些了。本文實際上並沒有貼原始碼,主要介紹一下思路,然後跟著流程圖,原始碼必須是自己讀並進行程式碼除錯才是有效果的。

Rxjava之路

這裡mark一下,希望通過閱讀Rxjava, 自己可以實現一個簡易的函式式流程。

NotRxJava guide for lazy folks中作者嫌Rxjava程式碼量大,於是介紹了一下自己的思路。文中的程式碼並不能實現一個非常安全可靠的程式碼庫,但是其思路很值得學習。

另谷歌開源了ageragithub,也是一個函式式的例子,程式碼量比Rxjava要少許多,其亮點是實現了資料的分離,“Push event,pull data model”是其目標。其原始碼思路非常清晰,簡直是寫程式碼的典範。github,MaterialDesignExample中是MaterialDesign使用的例子,其中使用agera對網路訪問到資料渲染到流程進行控制,資料來源是知乎日報,感興趣的可以看下。

參考

gank.io/post/560e15…
blog.csdn.net/wl9739/arti…
yarikx.github.io/NotRxJava/

相關文章