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方法最終會遍歷數組內的泛型數據,並通過把這些數據原封不動的依次分發到我們註冊的方法內