RxJava之just與from源碼解讀

上一節我們主要講的是RxJava的入門之create的源碼解讀,讓我們對RxJava有了初步的認識,本來這篇文章應該前些天寫的,但是由於最近工作比較忙,今天晚上,不知道怎麼的失眠睡不着,於是乎想起來做點什麼,便有了現在的這篇文章。好,廢話不多說,我們現在開始進入正題。
首先我們來看下下面這些代碼:

public static void just() {
        List<Integer> items = new ArrayList<>();
        items.add(1);
        items.add(10);
        items.add(100);
        items.add(200);
        Observable.just(items)
                .subscribe(new Observer<List<Integer>>() {
                    @Override
                    public void onCompleted() {
                        Log.d("test", "OnComplete");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("test", e.toString());
                    }

                    @Override
                    public void onNext(List<Integer> integers) {
                        for (int i = 0; i <integers.size();i++){
                 Log.d("test",String.valueOf(integers.get(i)));
                        }
                    }
                });
    }

    public static void from() {
        List<Integer> items = new ArrayList<>();
        items.add(1);
        items.add(10);
        items.add(100);
        items.add(200);
        Observable.from(items)
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onCompleted() {
                        Log.d("test", "OnComplete");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("test", e.toString());
                    }

                    @Override
                    public void onNext(Integer integers) {
                        Log.d("test", "Item is " +       String.valueOf(integers));
                    }
                });
    }

上面主要貼的是一個just函數與一個from函數,代碼上大家看下他們具體有什麼差別。

  1. 我們看到傳入的都是一個list,所以打印出來的內容都是一樣的,但是默認最後都會執行onComplete這個方法,打印出OnComplete字符串。
  2. 其次subscribe這個方法中的入參just是一個list類型,from是一個Integer類型,這說明當需要循環完list中的數據時,from需要調用4次onNext,而just之需要調用一次OnNext(以本例子中list中有4個字符串爲例),所以當我們需要在一個界面展示一個list的時候,我們就應該使用just,這樣只會刷新一次界面,from的話會調用4次,最後展示的可能就不是我們想要的結果的列表。
    總結了上面的結論,我們再來看下這兩個函數具體是怎麼實現的?
    首先來說下from,看下圖:

    這裏寫圖片描述

我們看到from中的入參是一個Interable類型的,而很多的集合類都實現了這一個接口,比如我們前面舉例的list,繼承自Collection,而Collection是繼承自Interable的。
當我們調用from的時候,我們new了一個OnSubscribeFromIterable對象,我們知道實現OnSubscribe接口的類有好多個,OnSubscribeFromIterable便是其中的一個,調用new這個方法,我們只是把我們創建出來的list保存到了一個變量當中,這裏暫且取名爲it,然後在from這個方法裏面又調用了一個create的方法,其實這個方法,和我們上一張講過的調用的是同一個方法,如下圖所示:

這裏寫圖片描述

調用上面的這個方法, 只是傳入一個OnSubscribe對象保存在了一個名叫OnSubscribe的變量當中,

接下來我們再來分析subScribe()過程,
和上一章講的一樣,當我們調用這個方法的時候,如下圖:

這裏寫圖片描述

仔細的觀察這個方法,我們看到當我們傳入我們創建的obServer的時候,他只是重新創建了一個Subscriber對象,而這個對象是繼承自Observer的,我們暫且把自己創建的叫observer1,新創建的叫做observer2,看下subscribe具體的實現過程:

 private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
     // validate and proceed
        if (subscriber == null) {
            throw new IllegalArgumentException("observer can not be null");
        }
        if (observable.onSubscribe == null) {
            throw new IllegalStateException("onSubscribe function can not be null.");
            /*
             * the subscribe function can also be overridden but generally that's not the appropriate approach
             * so I won't mention that in the exception
             */
        }

        // new Subscriber so onStart it
        subscriber.onStart();

        /*
         * See https://github.com/ReactiveX/RxJava/issues/216 for discussion on "Guideline 6.4: Protect calls
         * to user code from within an Observer"
         */
        // if not already wrapped
        if (!(subscriber instanceof SafeSubscriber)) {
            // assign to `observer` so we return the protected version
            subscriber = new SafeSubscriber<T>(subscriber);
        }

        // The code below is exactly the same an unsafeSubscribe but not used because it would 
        // add a significant depth to already huge call stacks.
        try {
            // allow the hook to intercept and/or decorate
            hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
            return hook.onSubscribeReturn(subscriber);
        } catch (Throwable e) {
            // special handling for certain Throwable/Error/Exception types
            Exceptions.throwIfFatal(e);
            // if an unhandled error occurs executing the onSubscribe we will propagate it
            try {
                subscriber.onError(hook.onSubscribeError(e));
            } catch (Throwable e2) {
                Exceptions.throwIfFatal(e2);
                // if this happens it means the onError itself failed (perhaps an invalid function implementation)
                // so we are unable to propagate the error correctly and will just throw
                RuntimeException r = new RuntimeException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);
                // TODO could the hook be the cause of the error in the on error handling.
                hook.onSubscribeError(r);
                // TODO why aren't we throwing the hook's return value.
                throw r;
            }
            return Subscriptions.unsubscribed();
        }
    }

其實在這寫代碼中,很多都是註釋,下面我們來看下邏輯,
1:當我們傳入observer2的時候,可以看到前面進行的一系列的判斷。2:有一個onStart方法,而這個方法在rxJava只是一個空實現,所以我們在這裏可以先不用管他。
3:把subscribe包裝成了一個SafeSubscriber對象。
4:接下來的這句話,纔是一切回調的開始,

hook.onSubscribeStart(observable,observable.onSubscribe).call(subscriber);

這裏的OnSubscribe對象,是我們第一次調用from的時候保存的OnSubscribe對象,即我們自己創建的匿名的OnSubscribe
對象,而這裏的入參,是我們第二次創建的observer2,當我們調用call方法的時候,即:

這裏寫圖片描述

call方法被執行,開始循環遍歷值(即上面提到的it),當it中有值的時候,會調用setProducer()方法,

這裏寫圖片描述

它也只是簡單的保存了一下值。
再來看看setProducer()方法,

這裏寫圖片描述

傳入了一個producer對象,當經過判斷以後,會執行最下面的request方法,即剛纔傳入的IterableProducer類中的request方法,下面看下這個方法:

@Override
        public void request(long n) {
            if (get() == Long.MAX_VALUE) {
                // already started with fast-path
                return;
            }
               if(n==Long.MAX_VALUE&&compareAndSet(0,Long.MAX_VALUE)) {
                fastpath();
            } else 
            if(n>0&&BackpressureUtils.getAndAddRequest(this, n) == 0L) {
                slowpath(n);
            }

        }

        void slowpath(long n) {
            // backpressure is requested
            final Subscriber<? super T> o = this.o;
            final Iterator<? extends T> it = this.it;

            long r = n;
            while (true) {
                long numToEmit = r;
                while (true) {
                    if (o.isUnsubscribed()) {
                        return;
                    } else if (it.hasNext()) {
                        if (--numToEmit >= 0) {
                            o.onNext(it.next());
                        } else
                            break;
                    } else if (!o.isUnsubscribed()) {
                        o.onCompleted();
                        return;
                    } else {
                        // is unsubscribed
                        return;
                    }
                }
                r = addAndGet(-r);
                if (r == 0L) {
                    // we're done emitting the number requested so
                    // return
                    return;
                }

            }
        }

        void fastpath() {
            // fast-path without backpressure
            final Subscriber<? super T> o = this.o;
            final Iterator<? extends T> it = this.it;

            while (true) {
                if (o.isUnsubscribed()) {
                    return;
                } else if (it.hasNext()) {
                    o.onNext(it.next());
                } else if (!o.isUnsubscribed()) {
                    o.onCompleted();
                    return;
                } else {
                    // is unsubscribed
                    return;
                }
            }
        }
    }

爲什麼要有一個producer接口對象呢?在上一章create的時候,我們是直接調用了observer中的onNext的方法,因爲它發射的是一個對象,而from,我們更像是把傳入的當成一個生產者,因爲在iterable中不止一個對象。發射的是多個對象。

在這個方法中,看到有一個fastpath與一個slowpath方法(我這裏爲什麼要寫這兩個方法,也不是很明白,如果知道的,可以在下面留言,告訴我一下哈,謝謝),在這兩個方法裏,都會去循環調用observer2中的onNext的方法,而observer2中的onNext的方法中又會去調用observer1中的方法,也就是我們自己寫的方法,這樣就完成了整個回調,而最後爲什麼會執行onComplete方法是因爲當迭代結束的時候,會執行onComplete方法,

最後在subscribe方法中return了一個Subscription對象,是方便我們unSubscribe,可以防止內存溢出。

下面我們來總結一下,

**1. 我們創建了OnSubscribe對象,
2. 我們創建了observer1
3. 創建了observer2
4. subscribe方法調用OnSubscribe中的call方法
5. 創建一個producer對象
6. producer循環發射list中的數據,不斷調用observer2中的onNext
7. observer2調用observer1中的onNext
8. 最後調用onComplete方法結束調用**

以上就是from的知識,感覺有點長,just方法的實現,請看下一節。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章