RxJava2实战--第二章 RxJava基础知识
第二章 RxJava基础知识
1. Observable
1.1 RxJava的使用三步骤
- 创建Observable
- 创建Observer
- 使用subscribe()进行订阅
Observable.just("Hello World")
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println(s);
}
});
subscribe()有多个重载方法:
Disposable subscribe()
Disposable subscribe(Consumer<? super T> onNext)
Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError)
Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
Action onComplete)
Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
Action onComplete, Consumer<? super Disposable> onSubscribe)
void subscribe(Observer<? super T> observer)
Consumer是消费者。
onComplete是一个Action,它与Consumer的区别如下:
- Action:无参数
- Consumer:单一参数类型
第五种重载例子:
Observable.just("Hello World")
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println(s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
System.out.println(throwable.getMessage());
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("onComplete");
}
}, new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
System.out.println("subscribe");
}
});
执行结果:
subscribe
Hello World
onComplete
Rxjava2中,Observable不在支持Subscriber,而是需要使用Observer作为观察者。
Observable.just("Hello World")
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("onSubscribe");
}
@Override
public void onNext(String s) {
System.out.println(s);
}
@Override
public void onError(Throwable e) {
System.out.println(e.getMessage());
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
});
执行结果:
onSubscribe
Hello World
onComplete
在Rxjava中,被观察者、观察者、subscribe()方法三者缺一不可。只有使用了subscribe(),被观察者才会开始发送数据。
1.2 RxJava2的五种观察者模式:
类型 | 描述 |
---|---|
Observable | 能够发射0或n个数据,并以成功或者错误事件终止 |
Flowable | 能够发射0或n个数据,并以成功或者错误事件终止。支持背压,可以控制数据源发射的速度 |
Single | 只发射单个数据或者错误事件 |
Completable | 从来不发射数据,只处理onComplete和onError事件。可以看成Rx的Runnable |
Maybe | 能够发射0或者1个数据,要么成功,要么失败。有点类似于Optional |
5种被观察者类型中只有Flowable支持背压。
1.3 do操作符
操作符 | 用途 |
---|---|
doOnSubscribe | 一旦观察者订阅了Observable,它就会被调用 |
doOnLifecycle | 可以在观察者订阅之后,设置是否取消订阅 |
doOnNext | 它产生的Observable每发射一项数据就会调用它一次,它的Consumer接受发射的数据项。一般用于在subscribe之前对数据进行处理 |
doOnEach | 它产生的Observable每发射一项数据就会调用它一次,不仅包括onNext,还包括onError和onComplete |
doAfterNext | 在onNext之后执行,而doOnNext()是在onNext之前执行 |
doOnComplete | 当产生的Observable在正常终止调用onComplete时会被调用 |
doFinally | 在当它产生的Observable终止之后会被调用,无论是正常终止还是异常终止。doFinally优先于doAfterTerminate的调用 |
doAfterTerminate | 注册一个Action,当Observable调用onComplete或onError时调用 |
public static void main(String[] args) {
Observable.just("Hello World")
.doOnNext(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("doOnNext:"+s);
}
}).doAfterNext(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("doAfterNext:"+s);
}
}).doOnComplete(new Action() {
@Override
public void run() throws Exception {
System.out.println("doOnComplete");
}
}).doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
System.out.println("doOnSubscribe:");
}
}).doAfterTerminate(new Action() {
@Override
public void run() throws Exception {
System.out.println("doAfterTerminate:");
}
}).doOnEach(new Consumer<Notification<String>>() {
@Override
public void accept(Notification<String> stringNotification) throws Exception {
System.out.println("doOnEach:"+(stringNotification.isOnNext()?"onNext":stringNotification.isOnComplete()?"onComplete":"onError")+" value:"+stringNotification.getValue());
}
}).doFinally(new Action() {
@Override
public void run() throws Exception {
System.out.println("doFinally:");
}
}).doOnLifecycle(new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
System.out.println("doOnLifecycle:"+disposable.isDisposed());
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("doOnLifecycle: run");
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("onSubscribe:");
}
@Override
public void onNext(String s) {
System.out.println("onNext:"+s);
}
@Override
public void onError(Throwable e) {
System.out.println("onError:"+e.getMessage());
}
@Override
public void onComplete() {
System.out.println("onComplete:");
}
});
执行结果:
doOnSubscribe:
doOnLifecycle:false
onSubscribe:
doOnNext:Hello World
doOnEach:onNext value:Hello World
onNext:Hello World
doAfterNext:Hello World
doOnComplete
doOnEach:onComplete value:null
onComplete:
doFinally:
doAfterTerminate:
doOnEach与doOnNext、doOnComplete()、doOnError执行顺序:谁在前面先执行谁。
doOnEach放到doOnNext上面执行:
...
.doOnEach(new Consumer<Notification<String>>() {
@Override
public void accept(Notification<String> stringNotification) throws Exception {
System.out.println("doOnEach:"+(stringNotification.isOnNext()?"onNext":stringNotification.isOnComplete()?"onComplete":"onError")+" value:"+stringNotification.getValue());
}
}).doOnNext(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("doOnNext:"+s);
}
})...
执行结果:
doOnSubscribe:
doOnLifecycle:false
onSubscribe:
doOnEach:onNext value:Hello World
doOnNext:Hello World
onNext:Hello World
doAfterNext:Hello World
doOnEach:onComplete value:null
doOnComplete
onComplete:
doFinally:
doAfterTerminate:
2.HotObservable和Cold Observable
2.1 Observabel分类
Observable 有 Cold 和 Hot 之分。
Hot Observable 无论有没有 Subscriber 订阅,事件始终都会发生。当 Hot Observable 有多个订阅者时,Hot Observable 与订阅者们的关系是一对多的关系,可以与多个订阅者共享信息。
Cold Observable是 只有 Subscriber 订阅时,才开始执行发射数据流的代码。并且 Cold Observable 和 Subscriber 只能是一对一的关系,当有多个不同的订阅者时,消息是重新完整发送的。也就是说对 Cold Observable 而言,有多个Subscriber的时候,他们各自的事件是独立的。
2.2 Cold Observable
Observable 的 just、creat、range、fromXXX 等操作符都能生成Cold Observable。
Consumer<Long> subscriber1 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println("subscriber1: "+aLong);
}
};
Consumer<Long> subscriber2 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber2: "+aLong);
}
};
Observable<Long> observable = Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Long> e) throws Exception {
Observable.interval(10, TimeUnit.MILLISECONDS,Schedulers.computation())
.take(Integer.MAX_VALUE)
.subscribe(e::onNext);
}
}).observeOn(Schedulers.newThread());
observable.subscribe(subscriber1);
observable.subscribe(subscriber2);
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
执行结果:
subscriber1: 0
subscriber2: 0
subscriber1: 1
subscriber2: 1
subscriber1: 2
subscriber2: 2
subscriber2: 3
subscriber1: 3
subscriber1: 4
subscriber2: 4
subscriber2: 5
subscriber1: 5
subscriber1: 6
subscriber2: 6
subscriber1: 7
subscriber2: 7
subscriber1: 8
subscriber2: 8
subscriber1: 9
subscriber2: 9
可以看出,subscriber1 和 subscriber2 的结果并不一定是相同的,二者是完全独立的。
尽管 Cold Observable 很好,但是对于某些事件不确定何时发生以及不确定 Observable 发射的元素数量,那还得使用 Hot Observable。比如:UI交互的事件、网络环境的变化、地理位置的变化、服务器推送消息的到达等等。
2.3 Clod Observable转Hot Observable
1. 使用publish,生成ConnectableObservable
使用 publish 操作符,可以让 Cold Observable 转换成 Hot Observable。它将原先的 Observable 转换成 ConnectableObservable。
Consumer<Long> subscriber1 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println("subscriber1: "+aLong);
}
};
Consumer<Long> subscriber2 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber2: "+aLong);
}
};
Consumer<Long> subscriber3 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber3: "+aLong);
}
};
ConnectableObservable<Long> observable = Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Long> e) throws Exception {
Observable.interval(10, TimeUnit.MILLISECONDS,Schedulers.computation())
.take(Integer.MAX_VALUE)
.subscribe(e::onNext);
}
}).observeOn(Schedulers.newThread()).publish();
observable.connect();
observable.subscribe(subscriber1);
observable.subscribe(subscriber2);
try {
Thread.sleep(20L);
} catch (InterruptedException e) {
e.printStackTrace();
}
observable.subscribe(subscriber3);
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
注意,生成的 ConnectableObservable 需要调用connect()才能真正执行。
执行结果:
subscriber1: 0
subscriber2: 0
subscriber1: 1
subscriber2: 1
subscriber1: 2
subscriber2: 2
subscriber3: 2
subscriber1: 3
subscriber2: 3
subscriber3: 3
subscriber1: 4
subscriber2: 4
subscriber3: 4
subscriber1: 5
subscriber2: 5
subscriber3: 5
subscriber1: 6
subscriber2: 6
subscriber3: 6
subscriber1: 7
subscriber2: 7
subscriber3: 7
subscriber1: 8
subscriber2: 8
subscriber3: 8
subscriber1: 9
subscriber2: 9
subscriber3: 9
subscriber1: 10
subscriber2: 10
subscriber3: 10
subscriber1: 11
subscriber2: 11
subscriber3: 11
可以看到,多个订阅的 Subscriber 共享同一事件。
在这里,ConnectableObservable 是线程安全的。
2. 使用Subject/Processor
Subject 和 Processor 的作用是相同的。Processor 是 RxJava2.x 新增的类,继承自 Flowable 支持背压控制。而 Subject 则不支持背压控制。
Consumer<Long> subscriber1 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println("subscriber1: "+aLong);
}
};
Consumer<Long> subscriber2 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber2: "+aLong);
}
};
Consumer<Long> subscriber3 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber3: "+aLong);
}
};
Observable<Long> observable = Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Long> e) throws Exception {
Observable.interval(10, TimeUnit.MILLISECONDS,Schedulers.computation())
.take(Integer.MAX_VALUE)
.subscribe(e::onNext);
}
}).observeOn(Schedulers.newThread());
PublishSubject<Long> subject = PublishSubject.create();
observable.subscribe(subject);
subject.subscribe(subscriber1);
subject.subscribe(subscriber2);
try {
Thread.sleep(20L);
} catch (InterruptedException e) {
e.printStackTrace();
}
subject.subscribe(subscriber3);
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
执行结果跟上面使用 publish 操作符是一样的。
Subject 既是 Observable 又是 Observer(Subscriber)。
当 Subject 作为 Subscriber 时,它可以订阅目标 Cold Observable 使对方开始发送事件。同时它又作为Observable 转发或者发送新的事件,让 Cold Observable 借助 Subject 转换为 Hot Observable。
注意,Subject 并不是线程安全的,如果想要其线程安全需要调用toSerialized()
方法。(在RxJava1.x的时代还可以用 SerializedSubject 代替 Subject,但是在RxJava2.x以后SerializedSubject不再是一个public class)
然而,很多基于 EventBus 改造的 RxBus 并没有这么做,包括我以前也写过这样的 RxBus 😦 。这样的做法是非常危险的,因为会遇到并发的情况。
2.4 Hot Observable 转Clod Observable
1. ConnectableObservable的refCount操作符
reactivex官网的解释是 :
make a Connectable Observable behave like an ordinary Observable .
RefCount操作符把从一个可连接的 Observable 连接和断开的过程自动化了。它操作一个可连接的Observable,返回一个普通的Observable。当第一个订阅者订阅这个Observable时,RefCount连接到下层的可连接Observable。RefCount跟踪有多少个观察者订阅它,直到最后一个观察者完成才断开与下层可连接Observable的连接。
如果所有的订阅者都取消订阅了,则数据流停止。如果重新订阅则重新开始数据流。
Consumer<Long> subscriber1 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println("subscriber1: "+aLong);
}
};
Consumer<Long> subscriber2 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber2: "+aLong);
}
};
ConnectableObservable<Long> connectableObservable = Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Long> e) throws Exception {
Observable.interval(10, TimeUnit.MILLISECONDS,Schedulers.computation())
.take(Integer.MAX_VALUE)
.subscribe(e::onNext);
}
}).observeOn(Schedulers.newThread()).publish();
connectableObservable.connect();
Observable<Long> observable = connectableObservable.refCount();
Disposable disposable1 = observable.subscribe(subscriber1);
Disposable disposable2 = observable.subscribe(subscriber2);
try {
Thread.sleep(20L);
} catch (InterruptedException e) {
e.printStackTrace();
}
disposable1.dispose();
disposable2.dispose();
System.out.println("重新开始数据流");
disposable1 = observable.subscribe(subscriber1);
disposable2 = observable.subscribe(subscriber2);
try {
Thread.sleep(20L);
} catch (InterruptedException e) {
e.printStackTrace();
}
执行结果:
subscriber1: 0
subscriber2: 0
subscriber1: 1
subscriber2: 1
重新开始数据流
subscriber1: 0
subscriber2: 0
subscriber1: 1
subscriber2: 1
如果不是所有的订阅者都取消了订阅,只取消了部分。部分的订阅者重新开始订阅,则不会从头开始数据流。
Consumer<Long> subscriber1 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println("subscriber1: "+aLong);
}
};
Consumer<Long> subscriber2 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber2: "+aLong);
}
};
Consumer<Long> subscriber3 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber3: "+aLong);
}
};
ConnectableObservable<Long> connectableObservable = Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Long> e) throws Exception {
Observable.interval(10, TimeUnit.MILLISECONDS,Schedulers.computation())
.take(Integer.MAX_VALUE)
.subscribe(e::onNext);
}
}).observeOn(Schedulers.newThread()).publish();
connectableObservable.connect();
Observable<Long> observable = connectableObservable.refCount();
Disposable disposable1 = observable.subscribe(subscriber1);
Disposable disposable2 = observable.subscribe(subscriber2);
observable.subscribe(subscriber3);
try {
Thread.sleep(20L);
} catch (InterruptedException e) {
e.printStackTrace();
}
disposable1.dispose();
disposable2.dispose();
System.out.println("subscriber1、subscriber2 重新订阅");
disposable1 = observable.subscribe(subscriber1);
disposable2 = observable.subscribe(subscriber2);
try {
Thread.sleep(20L);
} catch (InterruptedException e) {
e.printStackTrace();
}
执行结果:
subscriber1: 0
subscriber2: 0
subscriber3: 0
subscriber1: 1
subscriber2: 1
subscriber3: 1
subscriber1、subscriber2 重新订阅
subscriber3: 2
subscriber1: 2
subscriber2: 2
subscriber3: 3
subscriber1: 3
subscriber2: 3
subscriber3: 4
subscriber1: 4
subscriber2: 4
在这里,subscriber1和subscriber2先取消了订阅,subscriber3并没有取消订阅。之后,subscriber1和subscriber2又重新订阅。最终subscriber1、subscriber2、subscriber3的值保持一致。
2. Observable的share操作符
share操作符封装了publish().refCount()调用,可以看其源码。
/**
* Returns a new {@link ObservableSource} that multicasts (shares) the original {@link ObservableSource}. As long as
* there is at least one {@link Observer} this {@link ObservableSource} will be subscribed and emitting data.
* When all subscribers have disposed it will dispose the source {@link ObservableSource}.
* <p>
* This is an alias for {@link #publish()}.{@link ConnectableObservable#refCount()}.
* <p>
* ![](//upload-images.jianshu.io/upload_images/2613397-81dcef165b69aca2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code share} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an {@code ObservableSource} that upon connection causes the source {@code ObservableSource} to emit items
* to its {@link Observer}s
* @see <a href="http://reactivex.io/documentation/operators/refcount.html">ReactiveX operators documentation: RefCount</a>
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Observable<T> share() {
return publish().refCount();
}
总结:
理解了 Hot Observable 和 Cold Observable 的区别才能够写出更好Rx代码。同理,也能理解Hot & Cold Flowable。再者,在其他语言的Rx版本中包括 RxSwift、RxJS 等也存在 Hot Observable 和 Cold Observable 这样的概念。
3. Flowable
Flowable支持堵塞式背压。Flowable可以看成Observable新的实现,它支持背压,同时实现Reactive Streams的Publisher接口。Flowable所有的操作符强制支持背压,不过幸运的是,Flowable中的操作符大多与Observable类似。
Flowable 和Observable使用场景的区别:
1使用Observable较好的场景
- 一般处理最大不超过1000条数据,并且几乎不会出现内存溢出
- GUI鼠标事件,基本不会背压(可以结合 sampling/debouncing操作)
- 处理同步流
2 使用Flowable较好的场景
- 处理以某种方式产生超过10KB的元素
- 文件读取与分析
- 读取数据库记录,也是一个堵塞的和基于拉取模式
- 网络I/O
- 创建一个响应式非堵塞接口
4. Single、Completable和Maybe
4.1 Single
从SingleEmitter的源码可以看出,Single 只有 onSuccess 和 onError 事件。
/**
* Copyright (c) 2016-present, RxJava Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the specific language governing permissions and limitations under the License.
*/
package io.reactivex;
import io.reactivex.annotations.*;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Cancellable;
/**
* Abstraction over an RxJava {@link SingleObserver} that allows associating
* a resource with it.
* <p>
* All methods are safe to call from multiple threads.
* <p>
* Calling onSuccess or onError multiple times has no effect.
*
* @param <T> the value type to emit
*/
public interface SingleEmitter<T> {
/**
* Signal a success value.
* @param t the value, not null
*/
void onSuccess(@NonNull T t);
/**
* Signal an exception.
* @param t the exception, not null
*/
void onError(@NonNull Throwable t);
/**
* Sets a Disposable on this emitter; any previous Disposable
* or Cancellation will be unsubscribed/cancelled.
* @param s the disposable, null is allowed
*/
void setDisposable(@Nullable Disposable s);
/**
* Sets a Cancellable on this emitter; any previous Disposable
* or Cancellation will be unsubscribed/cancelled.
* @param c the cancellable resource, null is allowed
*/
void setCancellable(@Nullable Cancellable c);
/**
* Returns true if the downstream cancelled the sequence.
* @return true if the downstream cancelled the sequence
*/
boolean isDisposed();
}
其中,onSuccess()用于发射数据(在Observable/Flowable中使用onNext()来发射数据)。而且只能发射一个数据,后面即使再发射数据也不会做任何处理。
Single的SingleObserver中只有onSuccess、onError,并没有onComplete。这是 Single 跟其他四种被观察者最大的区别。
Single.create(new SingleOnSubscribe<String>() {
@Override
public void subscribe(@NonNull SingleEmitter<String> e) throws Exception {
e.onSuccess("test");
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println(s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
throwable.printStackTrace();
}
});
上面的代码,由于Observer中有两个Consumer,还可以进一步简化成
Single.create(new SingleOnSubscribe<String>() {
@Override
public void subscribe(@NonNull SingleEmitter<String> e) throws Exception {
e.onSuccess("test");
}
}).subscribe(new BiConsumer<String, Throwable>() {
@Override
public void accept(String s, Throwable throwable) throws Exception {
System.out.println(s);
}
});
Single 可以通过toXXX方法转换成Observable、Flowable、Completable以及Maybe。
4.2 Completable
Completable在创建后,不会发射任何数据。从CompletableEmitter的源码可以看到
/**
* Copyright (c) 2016-present, RxJava Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the specific language governing permissions and limitations under the License.
*/
package io.reactivex;
import io.reactivex.annotations.*;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Cancellable;
/**
* Abstraction over an RxJava {@link CompletableObserver} that allows associating
* a resource with it.
* <p>
* All methods are safe to call from multiple threads.
* <p>
* Calling onComplete or onError multiple times has no effect.
*/
public interface CompletableEmitter {
/**
* Signal the completion.
*/
void onComplete();
/**
* Signal an exception.
* @param t the exception, not null
*/
void onError(@NonNull Throwable t);
/**
* Sets a Disposable on this emitter; any previous Disposable
* or Cancellation will be disposed/cancelled.
* @param d the disposable, null is allowed
*/
void setDisposable(@Nullable Disposable d);
/**
* Sets a Cancellable on this emitter; any previous Disposable
* or Cancellation will be disposed/cancelled.
* @param c the cancellable resource, null is allowed
*/
void setCancellable(@Nullable Cancellable c);
/**
* Returns true if the downstream disposed the sequence.
* @return true if the downstream disposed the sequence
*/
boolean isDisposed();
}
Completable 只有 onComplete 和 onError 事件,同时 Completable 并没有map、flatMap等操作符,它的操作符比起 Observable/Flowable 要少得多。
我们可以通过fromXXX操作符来创建一个Completable。这是一个Completable版本的Hello World。
Completable.fromAction(new Action() {
@Override
public void run() throws Exception {
System.out.println("Hello World");
}
}).subscribe();
Completable 经常会结合andThen操作符
Completable.create(new CompletableOnSubscribe() {
@Override
public void subscribe(@NonNull CompletableEmitter emitter) throws Exception {
try {
TimeUnit.SECONDS.sleep(1);
emitter.onComplete();
} catch (InterruptedException e) {
emitter.onError(e);
}
}
}).andThen(Observable.range(1, 10))
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer) throws Exception {
System.out.println(integer);
}
});
在这里emitter.onComplete()执行完之后,表明Completable已经完全执行完毕,接下来是执行andThen里的操作。
1
2
3
4
5
6
7
8
9
10
在Completable中,andThen有多个重载的方法,正好对应了五种被观察者的类型
Completable andThen(CompletableSource next)
<T> Maybe<T> andThen(MaybeSource<T> next)
<T> Observable<T> andThen(ObservableSource<T> next)
<T> Flowable<T> andThen(Publisher<T> next)
<T> Single<T> andThen(SingleSource<T> next)
Completable 也可以通过toXXX方法转换成Observable、Flowable、Single以及Maybe。
4.3 Maybe
Maybe 是 RxJava2.x 之后才有的新类型,可以看成是Single和Completable的结合。
Maybe创建之后,MaybeEmitter 和 SingleEmitter 一样并没有onNext()方法,同样需要通过onSuccess()方法来发射数据。
Maybe.create(new MaybeOnSubscribe<String>() {
@Override
public void subscribe(@NonNull MaybeEmitter<String> e) throws Exception {
e.onSuccess("testA");
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("s="+s);
}
});
结果:
s=testA
Maybe也只能发射0或者1个数据,即使发射多个数据,后面发射的数据也不会处理。
Maybe.create(new MaybeOnSubscribe<String>() {
@Override
public void subscribe(@NonNull MaybeEmitter<String> e) throws Exception {
e.onSuccess("testA");
e.onSuccess("testB");
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("s="+s);
}
});
打印出来的结果仍然是 :
s=testA
跟第一次执行的结果是一致的。
如果MaybeEmitter先调用了onComplete(),即使后面再调用了onSuccess()也不会发射任何数据。
Maybe.create(new MaybeOnSubscribe<String>() {
@Override
public void subscribe(@NonNull MaybeEmitter<String> e) throws Exception {
e.onComplete();
e.onSuccess("testA");
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("s="+s);
}
});
这次就没有打印任何数据了。
我们对上面的代码再做一下修改,在subscribe()中也加入onComplete(),看看打印出来的结果会是这样的?因为SingleObserver中是没有onComplete()方法。
Maybe.create(new MaybeOnSubscribe<String>() {
@Override
public void subscribe(@NonNull MaybeEmitter<String> e) throws Exception {
e.onComplete();
e.onSuccess("testA");
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("s=" + s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("Maybe onComplete");
}
});
打印结果:
Maybe onComplete
通过查看Maybe相关的源码
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Disposable subscribe(Consumer<? super T> onSuccess, Consumer<? super Throwable> onError,
Action onComplete) {
ObjectHelper.requireNonNull(onSuccess, "onSuccess is null");
ObjectHelper.requireNonNull(onError, "onError is null");
ObjectHelper.requireNonNull(onComplete, "onComplete is null");
return subscribeWith(new MaybeCallbackObserver<T>(onSuccess, onError, onComplete));
}
我们可以得到,Maybe在没有数据发射时候subscribe会调用MaybeObserver的onComplete()。如果Maybe有数据发射或者调用了onError(),是不会再执行MaybeObserver的onComplete()。
我们也可以将 Maybe 转换成Observable、Flowable、Single,只需相应地调用toObservable()、toFlowable()、toSingle()。
5.Subject和Processor
5.1 Subject
Subject 既是 Observable 又是 Observer(Subscriber)。官网称 Subject 可以看成是一个桥梁或者代理。
分类:
Subject包含四种类型分别是AsyncSubject、BehaviorSubject、ReplaySubject和PublishSubject。
Subject | 发射行为 |
---|---|
AsyncSubject | 不论订阅发生在什么时候,只会发射最后一个数据 |
BehaviorSubject | 发送订阅之前一个数据和订阅之后的全部数据 |
ReplaySubject | 不论订阅发生在什么时候,都发射全部数据 |
PublishSubject | 发送订阅之后全部数据 |
1 AsyncSubject
Observer会接收AsyncSubject的onComplete()之前的最后一个数据。
AsyncSubject<String> subject = AsyncSubject.create();
subject.onNext("asyncSubject1");
subject.onNext("asyncSubject2");
subject.onComplete();
subject.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("asyncSubject:"+s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
System.out.println("asyncSubject onError"); //不输出(异常才会输出)
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("asyncSubject:complete"); //输出 asyncSubject onComplete
}
});
subject.onNext("asyncSubject3");
subject.onNext("asyncSubject4");
执行结果:
asyncSubject:asyncSubject2
asyncSubject:complete
改一下代码,将subject.onComplete()放在最后。
AsyncSubject<String> subject = AsyncSubject.create();
subject.onNext("asyncSubject1");
subject.onNext("asyncSubject2");
subject.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("asyncSubject:"+s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
System.out.println("asyncSubject onError"); //不输出(异常才会输出)
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("asyncSubject:complete"); //输出 asyncSubject onComplete
}
});
subject.onNext("asyncSubject3");
subject.onNext("asyncSubject4");
subject.onComplete();
执行结果:
asyncSubject:asyncSubject4
asyncSubject:complete
注意,subject.onComplete()必须要调用才会开始发送数据,否则Subscriber将不接收任何数据。
2 BehaviorSubject
Observer会接收到BehaviorSubject被订阅之前的最后一个数据,再接收订阅之后发射过来的数据。如果BehaviorSubject被订阅之前没有发送任何数据,则会发送一个默认数据。
BehaviorSubject<String> subject = BehaviorSubject.createDefault("behaviorSubject1");
subject.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("behaviorSubject:"+s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
System.out.println("behaviorSubject onError"); //不输出(异常才会输出)
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("behaviorSubject:complete"); //输出 behaviorSubject onComplete
}
});
subject.onNext("behaviorSubject2");
subject.onNext("behaviorSubject3");
执行结果:
behaviorSubject:behaviorSubject1
behaviorSubject:behaviorSubject2
behaviorSubject:behaviorSubject3
稍微改一下代码,在subscribe()之前,再发射一个事件。
BehaviorSubject<String> subject=BehaviorSubject.createDefault("behaviorSubject1");
subject.onNext("behaviorSubject2");
subject.onNext("behaviorSubject3");
subject.onNext("behaviorSubject4");
subject.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println(s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
throwable.printStackTrace();
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("complete");
}
});
subject.onNext("behaviorSubject5");
subject.onNext("behaviorSubject6");
执行结果:
behaviorSubject4
behaviorSubject5
behaviorSubject6
这次丢弃了默认值,而发射behaviorSubject4。
因为BehaviorSubject 每次只会发射调用subscribe()方法之前的最后一个事件和调用subscribe()方法之后的事件。
BehaviorSubject还可以缓存最近一次发出信息的数据。
3 ReplaySubject
ReplaySubject会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。
ReplaySubject<String> subject = ReplaySubject.create();
subject.onNext("replaySubject1");
subject.onNext("replaySubject2");
subject.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("replaySubject:"+s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
System.out.println("replaySubject onError"); //不输出(异常才会输出)
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("replaySubject:complete"); //输出 replaySubject onComplete
}
});
subject.onNext("replaySubject3");
subject.onNext("replaySubject4");
执行结果:
replaySubject:replaySubject1
replaySubject:replaySubject2
replaySubject:replaySubject3
replaySubject:replaySubject4
稍微改一下代码,将create()改成createWithSize(1)只缓存订阅前最后发送的1条数据
ReplaySubject<String> subject = ReplaySubject.createWithSize(1);
subject.onNext("replaySubject1");
subject.onNext("replaySubject2");
subject.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("replaySubject:"+s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
System.out.println("replaySubject onError"); //不输出(异常才会输出)
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("replaySubject:complete"); //输出 replaySubject onComplete
}
});
subject.onNext("replaySubject3");
subject.onNext("replaySubject4");
执行结果:
replaySubject:replaySubject2
replaySubject:replaySubject3
replaySubject:replaySubject4
这个执行结果跟BehaviorSubject是一样的。但是从并发的角度来看,ReplaySubject 在处理并发 subscribe() 和 onNext() 时会更加复杂。
ReplaySubject除了可以限制缓存数据的数量和还能限制缓存的时间。使用createWithTime()即可。
4 PublishSubject
Observer只接收PublishSubject被订阅之后发送的数据。
PublishSubject<String> subject = PublishSubject.create();
subject.onNext("publicSubject1");
subject.onNext("publicSubject2");
subject.onComplete();
subject.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("publicSubject:"+s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
System.out.println("publicSubject onError"); //不输出(异常才会输出)
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("publicSubject:complete"); //输出 publicSubject onComplete
}
});
subject.onNext("publicSubject3");
subject.onNext("publicSubject4");
执行结果:
publicSubject:complete
因为subject在订阅之前,已经执行了onComplete()方法,所以无法发射数据。稍微改一下代码,将onComplete()方法放在最后。
PublishSubject<String> subject = PublishSubject.create();
subject.onNext("publicSubject1");
subject.onNext("publicSubject2");
subject.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println("publicSubject:"+s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
System.out.println("publicSubject onError"); //不输出(异常才会输出)
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("publicSubject:complete"); //输出 publicSubject onComplete
}
});
subject.onNext("publicSubject3");
subject.onNext("publicSubject4");
subject.onComplete();
执行结果:
publicSubject:publicSubject3
publicSubject:publicSubject4
publicSubject:complete
可能错过的事件
Subject 作为一个Observable时,可以不停地调用onNext()来发送事件,直到遇到onComplete()才会结束。
PublishSubject<String> subject = PublishSubject.create();
subject.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println(s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
}
},new Action() {
@Override
public void run() throws Exception {
System.out.println("completed");
}
});
subject.onNext("Foo");
subject.onNext("Bar");
subject.onComplete();
执行结果:
Foo
Bar
completed
如果,使用 subsribeOn 操作符将 subject 切换到IO线程,再使用 Thread.sleep(2000) 让主线程休眠2秒。
PublishSubject<String> subject = PublishSubject.create();
subject.subscribeOn(Schedulers.io())
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
System.out.println(s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
}
},new Action() {
@Override
public void run() throws Exception {
System.out.println("completed");
}
});
subject.onNext("Foo");
subject.onNext("Bar");
subject.onComplete();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
执行结果:
completed
为何会缺少打印Foo和Bar?
因为,subject 发射元素的线程被指派到了 IO 线程,此时 IO 线程正在初始化还没起来,subject 发射前这两个元素Foo、Bar还在主线程中,主线程的这两个元素往 IO 线程转发的过程中由于 IO 线程还没有起来,所以就被丢弃了。此时,无论Thread睡了多少秒,Foo、Bar都不会被打印出来。
其实,解决办法也很简单,将subject改成使用Observable.create()来替代,它允许为每个订阅者精确控制事件的发送,这样就不会缺少打印Foo和Bar。
5.2 Processor
Processor 和 Subject 的作用相同的,既是观察者,也是被观察者。Subject 不支持背压,是 RxJava 1.x 继承过来的,Processor 继承 FlowableProcessor,支持背压。
不要使用 Flowable 或 Observable 里的方法,这样会将 Processor 转成一个 Flowable 或 Observable,用 Processor 内部重写的 create。
自己控制在合适的时机发射什么值,是 complete,还是 error。
AsyncProcessor
不论何时订阅,都只发射最后一个数据,如果因为异常而终止,不会释放任何数据,但是会向 Observer 传递一个异常通知。
BehaviorProcessor
发射订阅之前的一个数据和订阅之后的全部数据。如果订阅之前没有值,可以使用默认值。
PublishProcessor
从哪里订阅就从哪里发射数据。
ReplayProcessor
无论何时订阅,都发射所有的数据。
SerializedProcessor
其它 Processor 不要在多线程上发射数据,如果确实要在多线程上使用,用这个 Processor 封装,可以保证在一个时刻只在一个线程上执行。
UnicastProcessor
只能有一个观察者。
参考
Rxjava2实战