這篇博客的用法主要有 : zip,amb,combineLatest ,concatEager
zip
public static <T1, T2, R> Observable<R> zip(Observable<? extends T1> o1, Observable<? extends T2> o2, final Func2<? super T1, ? super T2, ? extends R> zipFunction)
... 支持N個參數的最終合併,這裏暫時只寫出兩個的
public static <R> Observable<R> zip(Iterable<? extends Observable<?>> ws, FuncN<? extends R> zipFunction)
public static <R> Observable<R> zip(Observable<? extends Observable<?>> ws, final FuncN<? extends R> zipFunction)
首先是
public static <T1, T2, R> Observable<R> zip(Observable<? extends T1> o1, Observable<? extends T2> o2, final Func2<? super T1, ? super T2, ? extends R> zipFunction) {
return just(new Observable<?>[] { o1, o2 }).lift(new OperatorZip<R>(zipFunction));
}
這個最終也是需要調用lift的轉化方法,lift方法真好用;注意這裏傳的Observable[],和from不同,just後續會直接會拿Observable[]去轉化,而不會把這個數組拆開;看下具體方法
public OperatorZip(Func2 f) {
this.zipFunction = Functions.fromFunc(f);
}
public static <T0, T1, R> FuncN<R> fromFunc(final Func2<? super T0, ? super T1, ? extends R> f) {
return new FuncN<R>() {
@SuppressWarnings("unchecked")
@Override
public R call(Object... args) {
if (args.length != 2) {
throw new RuntimeException("Func2 expecting 2 arguments.");
}
return f.call((T0) args[0], (T1) args[1]);
}
};
}
發現這裏會把zipFunction計算出的最終結果返回,如果是同一主線程還比較好理解,但如果多個異步,這塊是怎麼保證所有結果的同步呢;我們看下這個類的詳細
public final class OperatorZip<R> implements Operator<R, Observable<?>[]> {
@Override
public Subscriber<? super Observable[]> call(final Subscriber<? super R> child) {
final Zip<R> zipper = new Zip<R>(child, zipFunction);
final ZipProducer<R> producer = new ZipProducer<R>(zipper);
final ZipSubscriber subscriber = new ZipSubscriber(child, zipper, producer);
child.add(subscriber);
child.setProducer(producer);
return subscriber;
}
}
其中Zip這個類會存放我們傳進來的Subscriber,變量名字爲child,這個後面要用到
同樣,我們挑重點看,關心ZipSubscriber的方法;同樣我們只挑出onNext的執行方法
public void onNext(Observable[] observables) {
if (observables == null || observables.length == 0) {
child.onCompleted();
} else {
started = true;
zipper.start(observables, producer);
}
}
public void start(@SuppressWarnings("rawtypes") Observable[] os, AtomicLong requested) {
final Object[] subscribers = new Object[os.length];
for (int i = 0; i < os.length; i++) {
InnerSubscriber io = new InnerSubscriber();
subscribers[i] = io;
childSubscription.add(io);
}
this.requested = requested;
this.subscribers = subscribers; // full memory barrier: release all above
for (int i = 0; i < os.length; i++) {
os[i].unsafeSubscribe((InnerSubscriber) subscribers[i]);
}
}
這裏會把數組裏面的每個Observable都拆出來,並依次註冊InnerSubscriber,也是就每塊處理仍然都是獨立的
final class InnerSubscriber extends Subscriber{
...
public void onNext(Object t) {
try {
items.onNext(t);
} catch (MissingBackpressureException e) {
onError(e);
}
tick();
}
}
items是創建的RxRingBuffer對象
public class RxRingBuffer implements Subscription{
public void onNext(Object o) throws MissingBackpressureException {
...
synchronized (this) {
Queue<Object> q = queue;
if (q != null) {
mbe = !q.offer(on.next(o));
} else {
iae = true;
}
}
...
}
}
這個會創建一個Queue隊列去存放獲得的數據,後面會通過peek方法判斷這個queue裏面是否有值
注意到這個tick方法,每個InnerSubscriber的onNext都會執行到這裏;我們挑出重點看
...
final int length = subscribers.length;
...
while (true) {
final Object[] vs = new Object[length];
boolean allHaveValues = true;
for (int i = 0; i < length; i++) {
RxRingBuffer buffer = ((InnerSubscriber) subscribers[i]).items;
Object n = buffer.peek();
if (n == null) {
allHaveValues = false;
continue;
}
if (buffer.isCompleted(n)) {
child.onCompleted();
childSubscription.unsubscribe();
return;
} else {
vs[i] = buffer.getValue(n);
}
...
if (requested.get() > 0 && allHaveValues) {
try {
child.onNext(zipFunction.call(vs));
requested.decrementAndGet();
emitted++;
} catch (Throwable e) {
Exceptions.throwOrReport(e, child, vs);
return;
}
...
}
這裏有個while循環,當所有的Observable都正常回調值,也就是vs這個數組被填滿後,再把這個數組返給zipFunction處理,最後把處理後的值返給我們定義的Subscriber;所以即使我們發出多個網絡請求,最後也能正確處理
例子
Log.e(TAG, "zip start " );
Observable<Integer> observable1 = Observable.just(1).map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
try {
Thread.sleep(1000);
}catch (Exception e){}
return integer;
}
}).subscribeOn(Schedulers.io());
Observable<Boolean> observable2 = Observable.just(true).map(new Func1<Boolean, Boolean>() {
@Override
public Boolean call(Boolean aBoolean) {
try {
Thread.sleep(2000);
}catch (Exception e){}
return aBoolean;
}
}).subscribeOn(Schedulers.io());
Observable.zip(observable1, observable2, new Func2<Integer, Boolean, String>() {
@Override
public String call(Integer o, Boolean o2) {
return o + ":" + o2;
}
}).subscribe(new Action1<String>() {
@Override
public void call(String o) {
Log.e(TAG, "result = " + o);
}
});
這裏有兩個Observable,sleep不同時間,結果上會以時間最長的那個爲準
01-30 15:38:03.135 E/Main: zip start
01-30 15:38:05.156 E/Main: result = 1:true
public static <R> Observable<R> zip(Iterable<? extends Observable<?>> ws, FuncN<? extends R> zipFunction)
和之前的一樣,這個傳入的是一個集合;但必須是同類型的Observable集合
Observable<Integer> observable1 = Observable.just(1);
Observable<Integer> observable2 = Observable.just(2);
List<Observable<Integer>> list = Arrays.asList(observable1, observable2);
Observable.zip(list, new FuncN<String>() {
@Override
public String call(Object... args) {
int result = 0;
for (Object obj : args) {
result += ((Integer) obj).intValue();
}
return "result=" + result;
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e(TAG, s);
}
});
輸出結果
E/Main: result=3
public static <R> Observable<R> zip(Observable<? extends Observable<?>> ws, final FuncN<? extends R> zipFunction) {
return ws.toList().map(new Func1<List<? extends Observable<?>>, Observable<?>[]>() {
@Override
public Observable<?>[] call(List<? extends Observable<?>> o) {
return o.toArray(new Observable<?>[o.size()]);
}
}).lift(new OperatorZip<R>(zipFunction));
}
這個方法會把傳入Observable轉成集合再轉成數組,之後的流程和上面描述的基本一致
amb
public static <T> Observable<T> amb(Observable<? extends T> o1, Observable<? extends T> o2)
...... 超過兩個及以上的方法暫不寫出,因爲流程是一樣的
public static <T> Observable<T> amb(Iterable<? extends Observable<? extends T>> sources)
還是以最簡單的兩個爲例
public static <T> Observable<T> amb(Observable<? extends T> o1, Observable<? extends T> o2) {
return create(OnSubscribeAmb.amb(o1, o2)); }
public static <T> OnSubscribe<T> amb(Observable<? extends T> o1, Observable<? extends T> o2) {
List<Observable<? extends T>> sources = new ArrayList<Observable<? extends T>>();
sources.add(o1);
sources.add(o2);
return amb(sources);
}
public static <T> OnSubscribe<T> amb(final Iterable<? extends Observable<? extends T>> sources) {
return new OnSubscribeAmb<T>(sources);
}
我們發現最終還是會走到上面的第二個方法,而且值得注意的是,這些泛型都必須保持一致
我們挑重點看
public final class OnSubscribeAmb<T> implements OnSubscribe<T>{
@Override
public void call(final Subscriber<? super T> subscriber) {
final Selection<T> selection = new Selection<T>();
final AtomicReference<AmbSubscriber<T>> choice = selection.choice;
......
for (Observable<? extends T> source : sources) {
if (subscriber.isUnsubscribed()) {
break;
}
AmbSubscriber<T> ambSubscriber = new AmbSubscriber<T>(0, subscriber, selection);
selection.ambSubscribers.add(ambSubscriber);
AmbSubscriber<T> c;
if ((c = choice.get()) != null) {
// Already chose one, the rest can be skipped and we can clean up
selection.unsubscribeOthers(c);
return;
}
source.unsafeSubscribe(ambSubscriber);
}
}
}
所有的Observable都會註冊一個AmbSubscriber,而這個裏面傳入了我們最終輸出的subscriber;也是這個內部會處理我們的輸出方法,這裏的choice後面也會用到,仍然挑重點看
private static final class AmbSubscriber<T> extends Subscriber<T> {
......
@Override
public void onNext(T t) {
if (!isSelected()) {
return;
}
subscriber.onNext(t);
}
@Override
public void onCompleted() {
if (!isSelected()) {
return;
}
subscriber.onCompleted();
}
@Override
public void onError(Throwable e) {
if (!isSelected()) {
return;
}
subscriber.onError(e);
}
private boolean isSelected() {
if (chosen) {
return true;
}
if (selection.choice.get() == this) {
chosen = true;
return true;
} else {
if (selection.choice.compareAndSet(null, this)) {
selection.unsubscribeOthers(this);
chosen = true;
return true;
} else {
selection.unsubscribeLosers();
return false;
}
}
}
}
也就是說,只要接收到一次數據,就會給choice賦值,之後只有這一個Subscriber會正常返回true,也就是正常分發;之後的全部返回false,並且全部解除註冊;
unsubscribeLosers,顧名思義,失敗的全部解除;
amb其實就是一種競爭的隊列,第一個到達的會正常返回,之後的全部銷燬
例子
Log.e(TAG, "amb start ");
Observable observable1 = Observable.just(1).subscribeOn(Schedulers.io()).map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer o) {
try {
Thread.sleep(2000);
} catch (Exception e) {
}
return o;
}
});
Observable observable2 = Observable.just(2).subscribeOn(Schedulers.io()).map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer o) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
return o;
}
});
Observable.amb(observable1, observable2).subscribe(new Action1() {
@Override
public void call(Object o) {
Log.e(TAG, "result= " + o);
}
});
第一個sleep時間比第二個要長,第二個要先到達,第一個會被取消掉;輸出結果
01-30 16:23:38.681 5595-5595 E/Main: amb start
01-30 16:23:39.705 5595-5616 E/Main: result= 2
combineLatest
public static <T1, T2, R> Observable<R> combineLatest(Observable<? extends T1> o1, Observable<? extends T2> o2, Func2<? super T1, ? super T2, ? extends R> combineFunction)
......
public static <T, R> Observable<R> combineLatest(List<? extends Observable<? extends T>> sources, FuncN<? extends R> combineFunction)
public static <T, R> Observable<R> combineLatest(Iterable<? extends Observable<? extends T>> sources, FuncN<? extends R> combineFunction)
以兩個的爲例
public static <T1, T2, R> Observable<R> combineLatest(Observable<? extends T1> o1, Observable<? extends T2> o2, Func2<? super T1, ? super T2, ? extends R> combineFunction) {
return combineLatest(Arrays.asList(o1, o2), Functions.fromFunc(combineFunction));
}
public static <T, R> Observable<R> combineLatest(List<? extends Observable<? extends T>> sources, FuncN<? extends R> combineFunction) {
return create(new OnSubscribeCombineLatest<T, R>(sources, combineFunction));
}
這個方法最終會組成list調用下面的list的方法
public final class OnSubscribeCombineLatest<T, R> implements OnSubscribe<R> {
public OnSubscribeCombineLatest(Iterable<? extends Observable<? extends T>> sourcesIterable,
FuncN<? extends R> combiner) {
this(null, sourcesIterable, combiner, RxRingBuffer.SIZE, false);
}
public void call(Subscriber<? super R> s) {
Observable<? extends T>[] sources = this.sources;
int count = 0;
......
if (sources == null) {
if (sourcesIterable instanceof List) {
List list = (List)sourcesIterable;
sources = (Observable[])list.toArray(new Observable[list.size()]);
count = sources.length;
} else {
......
}
}
} else {
count = sources.length;
}
if (count == 0) {
s.onCompleted();
return;
}
LatestCoordinator<T, R> lc = new LatestCoordinator<T, R>(s, combiner, count, bufferSize, delayError);
lc.subscribe(sources);
}
}
傳入的Observable會轉成一個數組source,計算出數組的大小count,然後這裏會把subscrbier和combiner轉化方法都保存到LastestCoordinator裏處理,再看下這個具體類
static final class LatestCoordinator<T, R> extends AtomicInteger implements Producer, Subscription {
static final Object MISSING = new Object();
public LatestCoordinator(Subscriber<? super R> actual,
FuncN<? extends R> combiner,
int count, int bufferSize, boolean delayError) {
this.actual = actual;
this.combiner = combiner;
this.count = count;
this.bufferSize = bufferSize;
this.delayError = delayError;
this.latest = new Object[count];
// latest集合會全部以MISSION填充,其實都是一樣的
Arrays.fill(latest, MISSING);
this.subscribers = new CombinerSubscriber[count];
this.queue = new SpscLinkedArrayQueue<Object>(bufferSize);
this.requested = new AtomicLong();
this.error = new AtomicReference<Throwable>();
}
public void subscribe(Observable<? extends T>[] sources) {
Subscriber<T>[] as = subscribers;
int len = as.length;
for (int i = 0; i < len; i++) {
as[i] = new CombinerSubscriber<T, R>(this, i);
}
lazySet(0); // release array contents
actual.add(this);
actual.setProducer(this);
for (int i = 0; i < len; i++) {
if (cancelled) {
return;
}
sources[i].subscribe(as[i]);
}
}
}
這裏會創建兩個和Observable數同樣大小的數組 latest和subscribers;
其中latest會存放每個Observable回調的結果,存放的內容和每個Observable是一一對應的,也就是每個Obs只對應一個,如果有新的結果,則會替換掉之前的;
subscribers會把當前即LatestCoordinator和此次要創建的subscriber索引i傳入,後面sources的註冊的subscriber一一對應;就是每個Observable都會對應一個唯一的CombinerSubscriber,索引值就是上面的 i
static final class CombinerSubscriber<T, R> extends Subscriber<T> {
@Override
public void onNext(T t) {
if (done) return;
parent.combine(nl.next(t), index);
}
@Override
public void onError(Throwable t) {
......
parent.onError(t);
done = true;
parent.combine(null, index);
}
@Override
public void onCompleted() {
if (done) {
return;
}
done = true;
parent.combine(null, index);
}
void combine(Object value, int index) {
CombinerSubscriber<T, R> combinerSubscriber = subscribers[index];
int activeCount;
int completedCount;
int sourceCount;
boolean empty;
boolean allSourcesFinished;
synchronized (this) {
//數目等於傳入的Observable對象數
sourceCount = latest.length;
Object o = latest[index];
activeCount = active;
if (o == MISSING) {
active = ++activeCount;
//最開始這個一直是相等的,除非其中一個走了onError
//否則這個數最後疊加會和sourceCount相等
}
completedCount = complete;
if (value == null) {
complete = ++completedCount;
//完成數,正常走complete的value都是空的(Error也是空的)
} else {
latest[index] = combinerSubscriber.nl.getValue(value);
//每走一次onNext都會賦一次值,也就是會把之前的替換掉
}
allSourcesFinished = activeCount == sourceCount;
//所有的Observable都至少回調了一次onNext,也就是latest填滿了
empty = completedCount == sourceCount
|| (value == null && o == MISSING);
//全部結束(包括異常) 或者 其中出現了一次異常結果
//這個不太好理解,我們反推,否命題就是 : 事件還在繼續分發而且沒有發生過一次異常
if (!empty) {
if (value != null && allSourcesFinished) {
//latest被填充滿,同時此次回調的值不爲空
//也就是latest集合中的最後一個被填充後,後續再來值都會走這個方法
queue.offer(combinerSubscriber, latest.clone());
} else
if (value == null && error.get() != null) {
done = true;
}
} else {
done = true;
}
}
if (!allSourcesFinished && value != null) {
combinerSubscriber.requestMore(1);
return;
}
drain();
}
}
那麼重點就在drain方法了,摘出重點
void drain() {
if (getAndIncrement() != 0) {
return;
}
final Queue<Object> q = queue;
final Subscriber<? super R> a = actual;
int missed = 1;
for (;;) {
......
while (requestAmount != 0L) {
CombinerSubscriber<T, R> cs = (CombinerSubscriber<T, R>)q.peek();
boolean empty = cs == null;
......
if (empty) {
break;
}
q.poll();
Object[] array = (Object[])q.poll();
if (array == null) {
cancelled = true;
cancel(q);
a.onError(new IllegalStateException("Broken queue?! Sender received but not the array."));
return;
}
R v;
try {
v = combiner.call(array);
} catch (Throwable ex) {
cancelled = true;
cancel(q);
a.onError(ex);
return;
}
a.onNext(v);
......
}
......
missed = addAndGet(-missed);
if (missed == 0) {
break;
}
}
}
當queue集合不爲空的時候,摘出此時拷貝的latest副本,把這個副本的集合用我們定義的combiner方法處理後再傳給我們將要處理的subscriber;
所以對於多個的分發,Observable內子分發個數不一定要保持一樣,後續計算結果也並不需要同時抵達,這個是和zip的很大區別,zip方法要求分發數必須相同,否則後續的結果接受不到
例子
Log.e(TAG, "combineLastest start");
Observable observable1 = Observable.just(1,2).subscribeOn(Schedulers.io()).map(new Func1() {
@Override
public Object call(Object o) {
try {
Thread.sleep(2000);
} catch (Exception e) {
}
return o;
}
});
Observable observable2 = Observable.just(true, false).subscribeOn(Schedulers.io()).map(new Func1() {
@Override
public Object call(Object o) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
return o;
}
});
Observable.combineLatest(observable1, observable2, new Func2<Integer, Boolean, String>() {
@Override
public String call(Integer o, Boolean o2) {
return o + " : " + o2;
}
}).subscribe(new Action1() {
@Override
public void call(Object o) {
Log.e(TAG, "result= " + o);
}
});
作區分我做了sleep時間,實際輸出結果是
01-30 22:52:44.958 E/Main: combineLastest start
01-30 22:52:46.978 E/Main: result= 1 : true
01-30 22:52:46.982 E/Main: result= 1 : false
01-30 22:52:48.979 E/Main: result= 2 : false
我們發現接收到了三次,第一次要求是同時抵達;後續會按照上次的結果計算,第二次是false先抵達,然後取第一個obs1上次的1, 第三次則是2抵達,取obs2上次的false ; 這個的使用場景和我們登陸輸入賬號密碼有點類似
那我們如果改成 zip呢,輸出結果是
01-30 22:57:11.954 E/Main: result= 1 : true
01-30 22:57:13.956 E/Main: result= 2 : false
只有兩次,結果索引是匹配的,我們再把第一個obs刪掉一個數據,改成Observable.just(1),那麼輸出結果是
01-30 22:58:46.174 E/Main: result= 1 : true
結果就只剩一個了,因爲第二個索引個數不匹配
後面兩個方法和之前類似,變成了集合而已,而且也是泛型需要統一
concatEager
public static <T> Observable<T> concatEager(Observable<? extends T> o1, Observable<? extends T> o2)
......
public static <T> Observable<T> concatEager(Iterable<? extends Observable<? extends T>> sources)
public static <T> Observable<T> concatEager(Iterable<? extends Observable<? extends T>> sources, int capacityHint)
仍然以兩個的爲例
public final class OperatorEagerConcatMap<T, R> implements Operator<R, T> {
@Override
public Subscriber<? super T> call(Subscriber<? super R> t) {
EagerOuterSubscriber<T, R> outer = new EagerOuterSubscriber<T, R>(mapper, bufferSize, t);
outer.init();
return outer;
}
}
static final class EagerOuterSubscriber<T, R> extends Subscriber<T> {
public EagerOuterSubscriber(Func1<? super T, ? extends Observable<? extends R>> mapper, int bufferSize,
Subscriber<? super R> actual) {
this.mapper = mapper;
this.bufferSize = bufferSize;
this.actual = actual;
this.subscribers = new LinkedList<EagerInnerSubscriber<R>>();
this.wip = new AtomicInteger();
}
public void onNext(T t) {
Observable<? extends R> observable;
try {
observable = mapper.call(t);
} catch (Throwable e) {
Exceptions.throwOrReport(e, actual, t);
return;
}
EagerInnerSubscriber<R> inner = new EagerInnerSubscriber<R>(this, bufferSize);
if (cancelled) {
return;
}
synchronized (subscribers) {
if (cancelled) {
return;
}
subscribers.add(inner);
}
if (cancelled) {
return;
}
observable.unsafeSubscribe(inner);
drain();
}
}
這裏創建了一個LinkList存放後面註冊的EagerInnerSubscriber,按照順序添加,這個onNext裏面會依次回調添加進的Observable,並順序註冊上面的InnerSubscriber
static final class EagerInnerSubscriber<T> extends Subscriber<T> {
final EagerOuterSubscriber<?, T> parent;
final Queue<Object> queue;
@Override
public void onNext(T t) {
//每次獲取到數據都會把這個數據添加到這個queue隊列中
queue.offer(nl.next(t));
parent.drain();
}
@Override
public void onCompleted() {
done = true;
parent.drain();
}
}
數據會存放到這裏的queue隊列裏
void drain() {
if (wip.getAndIncrement() != 0) {
return;
}
int missed = 1;
......
final Subscriber<? super R> actualSubscriber = this.actual;
for (;;) {
......
EagerInnerSubscriber<R> innerSubscriber;
boolean outerDone = done;
synchronized (subscribers) {
//按照註冊的順序取出第一個
innerSubscriber = subscribers.peek();
}
boolean empty = innerSubscriber == null;
......
if (!empty) {
......
Queue<Object> innerQueue = innerSubscriber.queue;
boolean innerDone = false;
for (;;) {
outerDone = innerSubscriber.done;
//判斷這個subscriber是否已經分發完成
//回調onComplete會把這個done設成ture
Object v = innerQueue.peek();
//取出這個innersubscriber中第一個數據
empty = v == null;
.......
if (outerDone) {
Throwable innerError = innerSubscriber.error;
if (innerError != null) {
cleanup();
actualSubscriber.onError(innerError);
return;
} else
if (empty) {
synchronized (subscribers) {
subscribers.poll();
//如果這個innerSubscriber已經回調onCompleted
//同時裏面的queue數據已經被全部取出,就把這個對應的sub彈出
//這樣下次取的就是按順序的第二個subscriber
}
innerSubscriber.unsubscribe();
innerDone = true;
break;
}
}
if (empty) {
break;
}
innerQueue.poll();
//如果第一個數有值,則彈出queue的第一個數據,並把這個數據返給我們定義的subscriber
try {
actualSubscriber.onNext(nl.getValue(v));
} catch (Throwable ex) {
Exceptions.throwOrReport(ex, actualSubscriber, v);
return;
}
......
}
......
if (innerDone) {
//這個Observable已經完成,遍歷下一個
continue;
}
}
missed = wip.addAndGet(-missed);
if (missed == 0) {
return;
}
}
}
每次獲得結果都會根據需求判斷是否要循環遍歷,如果正好是第一個註冊的則輸出,如果非首個註冊的,則緩存數據,等待第一個完成再輸出這個緩存數據
這個實際輸出結果和concat類似,不同的是concat是按照Observable順序依次執行,等第一個有結果後再去執行第二個;
這個方法是可以同時執行,每次取到結果時候進行判斷,保持結果依次發出
例子
Observable observable1 = Observable.just(1).subscribeOn(Schedulers.io()).map(new Func1() {
@Override
public Object call(Object o) {
try {
Thread.sleep(2000);
} catch (Exception e) {
}
Log.e(TAG,"obs1獲得了結果");
return o;
}
});
Observable observable2 = Observable.just(2).subscribeOn(Schedulers.io()).map(new Func1() {
@Override
public Object call(Object o) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
Log.e(TAG,"obs2獲得了結果");
return o;
}
});
Observable.concatEager(observable1, observable2).subscribe(new Action1() {
@Override
public void call(Object o) {
Log.e(TAG, "result= " + o);
}
});
輸出結果是
01-31 00:19:23.597 E/Main: obs2獲得了結果
01-31 00:19:24.586 E/Main: obs1獲得了結果
01-31 00:19:24.586 E/Main: result= 1
01-31 00:19:24.586 E/Main: result= 2
同樣,如果我們換成concat方法,輸出則變成了
01-31 00:19:08.050 E/Main: obs1獲得了結果
01-31 00:19:08.050 E/Main: result= 1
01-31 00:19:09.054 E/Main: obs2獲得了結果
01-31 00:19:09.054 E/Main: result= 2
類似於我們的同步和異步概念