RxJava的Observable創建和發佈流程原理簡單分析

Rx框架從發佈以來已經被越來越多的人所認可,尤其是其類型轉換和線程自由切換可以大大減少代碼的回調層數,使代碼可讀性大大提高

我們先看一個例子

  Observable.just("1")
                .map(new Func1<String, Integer>() {
                    @Override
                    public Integer call(String s) {
                        System.out.println("first ->>> " + Thread.currentThread().getId());
                        return new Integer(s);
                    }
                })
                .flatMap(new Func1<Integer, Observable<Integer>>() {
                    @Override
                    public Observable<Integer> call(Integer integer) {
                        System.out.println("second ->>> " + Thread.currentThread().getId());
                        return Observable.just(integer.intValue() * 2);
                    }
                })
                .observeOn(Schedulers.newThread())
                .map(new Func1<Integer, String>() {
                    @Override
                    public String call(Integer integer) {
                        System.out.println("third ->>> " + Thread.currentThread().getId());
                        return "No." + integer;
                    }
                })
                .observeOn(Schedulers.newThread())
                .subscribe(new Action1<String>() {

                    @Override
                    public void call(String s) {
                        System.out.println("forth ->>> " + Thread.currentThread().getId());

                        System.out.println("result ->>> " + s);
                    }
                });

我們把字符串轉int後乘以2再加一個前綴返回,同時打印了執行操作的相應線程id,輸出結果是

first ->>> 1
second ->>> 1
third ->>> 15
forth ->>> 14
result ->>> No.2

可以發現前兩個是同一個發佈線程,而後面兩個我都設置了新的回調處理線程,所以後面兩個分別在不同的新線程,是不是很方便,具體線程是怎麼切換的我會在下一篇裏分析

我們先看一下Observable的創建方法

public static <T> Observable<T> create(OnSubscribe<T> f) {
        return new Observable<T>(hook.onCreate(f));
    }

Observable會創建一個OnSubscribe實例,而這個實例會被存放在當前Observable的成員變量中,注意存放的這個變量是final類型;一般我們並不會去自定義一個這個,用Rx提供的api就足夠了

接下來我們用常用方法分析一下

 Observable.just(1,2,3).subscribe(new Subscriber<Integer>() {
           @Override
           public void onCompleted() {
           }

           @Override
           public void onError(Throwable e) {
           }

           @Override
           public void onNext(Integer integer) {
               System.out.println("->>>> " + integer);
           }
       });

 

 這就是一個簡單的案列,會依次發佈1-3的數據,我們看一下just都做了啥

 public static <T> Observable<T> just(T t1, T t2, T t3) {
        return from((T[])new Object[] { t1, t2, t3 });
    }

public static <T> Observable<T> from(T[] array) {
        int n = array.length;
        if (n == 0) {
            return empty();
        } else
        if (n == 1) {
            return just(array[0]);
        }
        return create(new OnSubscribeFromArray<T>(array));
    }

我們可以看出,just會把數據包裝成一個數組再調用from方法,這兩個常用方法其實可以看成一個

其中OnSubscribeFromArray實現了OnSubscribe接口

調用just會把要發佈的數據組裝成功一個數據,然後把這個數據交付給OnSubscribeFromArray,然後把這個實例化的對象作爲OnSubscribe從而創建一個新的Observable對象,所以這裏只會返回一個Observable對象,那什麼時候纔會發佈數據呢?

然後是subscribe方法的調用

 public final Subscription subscribe(Subscriber<? super T> subscriber) {
        return Observable.subscribe(subscriber, this);
    }

 private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
    //忽略部分代碼,正常流程的大致意思
    subscriber.onStart();

    if (!(subscriber instanceof SafeSubscriber)) {
            // assign to `observer` so we return the protected version
            subscriber = new SafeSubscriber<T>(subscriber);
        }

    observable.onSubscribe.call(subscriber);
    return subscriber;
}

這裏會先執行subscriber的onStart方法,然後調用上面保存的OnSubscribe對象的call方法,把subscriber作爲參數傳進去,最後把subscribe作爲Subscription返回,其中subscribe本身實現了Subscription接口

這裏有個一SafeSubscriber,這個是SubScriber的子類,非這個類的都會被強制包裝成這個類型,至於爲什麼

private final SubscriptionList subscriptions;
private final Subscriber<?> subscriber;
 
protected Subscriber() {
        this(null, false);
}

protected Subscriber(Subscriber<?> subscriber, boolean shareSubscriptions) {
        this.subscriber = subscriber;
        this.subscriptions = shareSubscriptions && subscriber != null ? subscriber.subscriptions : new SubscriptionList();
    }

public class SafeSubscriber<T> extends Subscriber<T> {
    private final Subscriber<? super T> actual;

    public SafeSubscriber(Subscriber<? super T> actual) {
        super(actual);
        this.actual = actual;
    }
}

Subscribe中有兩個成員終型成員變量,我們默認傳空參數是不會給這兩個賦值的,而這兩個變量對後續發佈會有作用

Subscription只提供兩個方法,主要是解除註冊和相應的判斷,後續發佈判斷都會判斷這個依據,如果被解除註冊則後續的onNext, onError和onComplete都不會再通知

public interface Subscription {
    void unsubscribe();
    boolean isUnsubscribed();
}

那重點就回到OnSubscribe的call方法上

@Override
public void call(Subscriber<? super T> child) {
        child.setProducer(new FromArrayProducer<T>(child, array));
}

public void setProducer(Producer p) {
        long toRequest;
        boolean passToSubscriber = false;
        synchronized (this) {
            toRequest = requested;
            producer = p;
            if (subscriber != null) {
                // middle operator ... we pass thru unless a request has been made
                if (toRequest == NOT_SET) {
                    // we pass-thru to the next producer as nothing has been requested
                    passToSubscriber = true;
                }
            }
        }
        // do after releasing lock
        if (passToSubscriber) {
            subscriber.setProducer(producer);
        } else {
            // we execute the request with whatever has been requested (or Long.MAX_VALUE)
            if (toRequest == NOT_SET) {
                producer.request(Long.MAX_VALUE);
            } else {
                producer.request(toRequest);
            }
        }
}

call會調用上面創建的subscribe的setProducer方法,這個subscribe就是上面SafeSubscriber包裝的內部對象

而SafeSubscriber這個subscribe不爲空,其父類Subscriber的subscribe是空 的,requested則是默認初始值NOT_SET,所以最後這個會連調兩次最終到父類的方法,走到producer.request(Long.MAX_VALUE)

就是上面的new FromArrayProducer(...).request(Long.MAX_VALUE)

再看下這個類

 static final class FromArrayProducer<T> extends AtomicLong implements Producer {
        final Subscriber<? super T> child;
        final T[] array;
        public FromArrayProducer(Subscriber<? super T> child, T[] array) {
            this.child = child;
            this.array = array;
        }
    ...
}

參數一個是當前的subscribe,一個是初始化傳入的泛型數組

@Override
public void request(long n) {
    if (n < 0) {
          throw new IllegalArgumentException("n >= 0 required but it was " + n);
    }
    if (n == Long.MAX_VALUE) {
          if (BackpressureUtils.getAndAddRequest(this, n) == 0) {
               fastPath();
          }
     } else if (n != 0) {
         if (BackpressureUtils.getAndAddRequest(this, n) == 0) {
             slowPath(n);
        }
     }
 }

最終會執行到這裏的fastPath

void fastPath() {
     final Subscriber<? super T> child = this.child;
            
      for (T t : array) {
          if (child.isUnsubscribed()) {
             return;
          }
            child.onNext(t);
      }
            
     if (child.isUnsubscribed()) {
           return;
     }
     child.onCompleted();
}

這裏會依次調用child也就是我們註冊的Subscriber的onNext(),數組值取完後會調用onCompleted();而且onNext和onComplete前都會檢測Subscriber的註冊狀態,如果已經被解除則後續的都不會給回調回來

注:這裏的child是被封裝後的SafeSubscriber了,具體方法是

@Override
public void onCompleted() {
  if (!done) {
     done = true;
     try {
         actual.onCompleted();
        } catch (Throwable e) {
             ...
        }
    }
}

@Override
public void onNext(T args) {
  try {
     if (!done) {
         actual.onNext(args);
      }
     } catch (Throwable e) {
       ...
     }
}

也就是最終會回到我們最初註冊的那個subscriber內

總結:

1. Observable初始化添加數組會創建一個OnSubscriber實例存儲數組,不做具體操作

2. subscribe方法需要傳入我們自定義的Subscriber實現類我們叫做mySubscriber,就是接收到數據的處理方法;調用後會馬上調用mySubscriber的onStart()方法,然後把這個用SafeSubscriber包裝後,調用最開始創建的OnSubscriber的call方法,傳入這個包後的對象,並把這個對象當做Subscription操作類返回,這個操作類可以控制事件的解註冊判斷

3.OnSubscriber對象的call方法最終會遍歷數組內的泛型數據,並通過把這些數據原封不動的依次分發到我們註冊的方法內

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