目录
2.4、形象理解ObservableSource和Publisher有何异同
开篇
开始学习RxJava的时候忘记所有,仅仅就学习RxJava,单独看待,不需要和Retrofit等等其它库结合使用,当我们明白RxJava的操作符等一些列api怎么使用在什么场景下使用后再来结合Retrofit来进行网络请求等,这样或许会更加清晰点。
RxJava2 的5大基类及本章学习结构图
1、Flowable
1.1、Flowable简介
Flowable类,用于实现Reactive-Streams模式,并提供工厂方法,中间运算符以及使用反应式数据流的能力。
Reactive-Streams使用Flowable运行,Flowable实现了Publishers。因此,许多运算符直接接受Publishers,并允许与其他Reactive-Streams的实现进行直接交互操作
public abstract class Flowable<T> implements Publisher<T>
Flowable为操作符提供128个元素的默认缓冲区大小,可通过bufferSize() 方法获取,可通过系统参数rx2.buffer-size全局覆盖。但是大多数运算符都有重载,允许显式设置其内部缓冲区大小。
/** The default buffer size. */
static final int BUFFER_SIZE;
static {
BUFFER_SIZE = Math.max(16, Integer.getInteger("rx2.buffer-size", 128));
}
/**
* Returns the default internal buffer size used by most async operators.
* <p>The value can be overridden via system parameter {@code rx2.buffer-size}
* <em>before</em> the Flowable class is loaded.
* @return the default internal buffer size.
*/
public static int bufferSize() {
return BUFFER_SIZE;
}
1.2、Flowable官方图解
1)看到上图有点疑问,不是在说Flowable嘛,怎么图解里的说明是Observable呢?
2)其实在官方文档里面Flowable和Observable都使用的是上面这个图解,因此这两个类肯定是提供相似功能,既然是相似,那么这幅图就是他们的共性,那不同的地方是什么呢?
不同之处是:Flowable支持Backpressure,Observable不支持Backpressure;
3)Backpressure什么是?
看下面1.3节
1.3、Backpressure
Backpressure中文翻译过来是背压,这里推荐一篇很好的关于Backpressure说明的博客:关于RxJava最友好的文章——背压(Backpressure)
下面关于背压的说明是出自拉丁吴博客的内容,写的很通俗易懂
RxJava是一个观察者模式的架构,当这个架构中被观察者(Observable)和观察者(Subscriber)处在不同的线程环境中时,由于者各自的工作量不一样,导致它们产生事件和处理事件的速度不一样,这就会出现两种情况:
- 被观察者产生事件慢一些,观察者处理事件很快。那么观察者就会等着被观察者发送事件,(好比观察者在等米下锅,程序等待,这没有问题)。
- 被观察者产生事件的速度很快,而观察者处理很慢。那就出问题了,如果不作处理的话,事件会堆积起来,最终挤爆你的内存,导致程序崩溃。(好比被观察者生产的大米没人吃,堆积最后就会烂掉)。
下面我们用代码演示一下这种崩溃的场景:
//被观察者在主线程中,每1ms发送一个事件
Observable.interval(1, TimeUnit.MILLISECONDS)
//.subscribeOn(Schedulers.newThread())
//将观察者的工作放在新线程环境中
.observeOn(Schedulers.newThread())
//观察者处理每1000ms才处理一个事件
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.w("TAG","---->"+aLong);
}
});
拉丁吴对Backpressure的定义是:
背压是指在异步场景中,被观察者发送事件速度远快于观察者的处理速度的情况下,一种告诉上游的被观察者降低发送速度的策略
简而言之,背压是流速控制的一种策略。
需要强调两点:
- 背压策略的一个前提是异步环境,也就是说,被观察者和观察者处在不同的线程环境中。
- 背压(Backpressure)并不是一个像flatMap一样可以在程序中直接使用的操作符,他只是一种控制事件流速的策略。
关于背压(Backpressure)的解释拉丁吴说的很清楚了,要了解更多关于这方面的信息可以移步他的博客:关于RxJava最友好的文章——背压(Backpressure)
2、Observable
2.1、Observable简介
Observable类是不支持背压的,Observable是Reactive的一个抽象基类,Observable提供工厂方法,中间运算符以及消费同步和/或异步数据流的功能。
Observable类中的多数运算符接受一个或者多个ObservableSource,ObservableSource是非背压的基本接口,Observable实现了这个接口。
public abstract class Observable<T> implements ObservableSource<T>
默认情况下,Observable的为其运算符提供128个元素的缓冲区大小运行,可看考Flowable.bufferSize(),可以通过系统参数rx2.buffer-size全局覆盖。但是,大多数运算符都有重载,允许设置其内部缓冲区大小。
2.2、Observable官方图解
与Flowable是一样的
2.3、Flowable和Observable对比
在1.2节中已经说明了二者最大的区别。
官方也给出的解释是:
The design of this class was derived from the Reactive-Streams design and specification by removing any backpressure-related infrastructure and implementation detail, replacing the org.reactivestreams.Subscription with Disposable as the primary means to dispose of a flow.
中文翻译:
该类的设计源自Reactive-Streams设计和规范,通过删除任何与背压相关的基本结构和实现细节,将Disposable替换为org.reactivestreams.Subscription作为处理流的主要方式。
从代码层面上做简单的说明
Flowable实现了Publisher接口,Publisher源码如下
public interface Publisher<T> {
/**
* Request {@link Publisher} to start streaming data.
* <p>
* This is a "factory method" and can be called multiple times, each time starting a new {@link Subscription}.
* <p>
* Each {@link Subscription} will work for only a single {@link Subscriber}.
* <p>
* A {@link Subscriber} should only subscribe once to a single {@link Publisher}.
* <p>
* If the {@link Publisher} rejects the subscription attempt or otherwise fails it will
* signal the error via {@link Subscriber#onError}.
*
* @param s the {@link Subscriber} that will consume signals from this {@link Publisher}
*/
public void subscribe(Subscriber<? super T> s);
}
Observable实现了ObservableSource接口,ObservableSource源码如下
public interface ObservableSource<T> {
/**
* Subscribes the given Observer to this ObservableSource instance.
* @param observer the Observer, not null
* @throws NullPointerException if {@code observer} is null
*/
void subscribe(Observer<? super T> observer);
}
对比ObservableSource和Publisher,都有一个同名的接口subscribe()
2.4、形象理解ObservableSource和Publisher有何异同
ObservableSource:可观察源
Publisher:发布者
subscribe:订阅
Subscriber:订阅者
Observer:观察者
对于ObservableSource,可以将subscribe(Observer observer)理解为Observer通过subscribe订阅了ObservableSource
对于Publisher,可以将subscribe(Subscriber s)理解为Subscriber通过subscribe订阅了Publisher
上面的解释可能比较抽象,通俗的举个例子,来个角色扮演
第一组:报刊(ObservableSource)、报刊订阅者(Observer)、订阅报刊的行为(subscribe)
第二组:报刊发布人(Publisher)、报刊订阅者(Subscriber)、订阅报刊的行为(subscribe)
把这个场景串起来讲就是:报刊订阅者订阅了报刊,或者说报刊订阅者在报刊发布人手中订阅了报刊。
这其实是典型的观察者模式,所不同的是信息的发布者是ObservableSource还是Publisher,信息的订阅者是Observer还是Subscriber,统一的行为都是subscribe。
3、Single
3.1、Single简介
public abstract class Single<T> implements SingleSource<T>
Single实现了SingleSource
/**
* Represents a basic {@link Single} source base interface,
* consumable via an {@link SingleObserver}.
* <p>
* This class also serves the base type for custom operators wrapped into
* Single via {@link Single#create(SingleOnSubscribe)}.
*
* @param <T> the element type
* @since 2.0
*/
public interface SingleSource<T> {
/**
* Subscribes the given SingleObserver to this SingleSource instance.
* @param observer the SingleObserver, not null
* @throws NullPointerException if {@code observer} is null
*/
void subscribe(SingleObserver<? super T> observer);
}
Single类为单个值响应实现Reactive Pattern。
Single和Observable类似,所不同的是Single只能发出一个值,要么发射成功要么发射失败,也没有“onComplete”作为完成时的回调
Single类实现了基类SingleSource的接口,SingleObserver作为Single发出来的消息的默认消费者,SingleObserver通过subscribe(SingleObserver<? super T> observer)在Single中订阅消息
public interface SingleObserver<T> {
/**
* Provides the SingleObserver with the means of cancelling (disposing) the
* connection (channel) with the Single in both
* synchronous (from within {@code onSubscribe(Disposable)} itself) and asynchronous manner.
* @param d the Disposable instance whose {@link Disposable#dispose()} can
* be called anytime to cancel the connection
* @since 2.0
*/
void onSubscribe(Disposable d);
/**
* Notifies the SingleObserver with a single item and that the {@link Single} has finished sending
* push-based notifications.
* <p>
* The {@link Single} will not call this method if it calls {@link #onError}.
*
* @param value
* the item emitted by the Single
*/
void onSuccess(T value);
/**
* Notifies the SingleObserver that the {@link Single} has experienced an error condition.
* <p>
* If the {@link Single} calls this method, it will not thereafter call {@link #onSuccess}.
*
* @param e
* the exception encountered by the Single
*/
void onError(Throwable e);
}
3.2、Single与Observable的区别
Single只能发送单个消息,不能发送消息流,而且观察者接收到消息也只有两种情况,要么接收成功,要么接收失败
3.3、Single官方图解
4、Completable
4.1、Completable简介
Completable类表示延迟计算,没有任何值,只表示完成或异常。
Completable的行为类似于Observable,在计算完成后只能发出完成或错误信号,由onComplete或onError接口来处理,没有onNext或onSuccess等回调接口
Completable实现了基类CompletableSource的接口,CompletableObserver通过subscribe()方法在Completable处订阅消息。
Completable遵循协议:onSubscribe (onComplete | onError)
public abstract class Completable implements CompletableSource
public interface CompletableSource {
/**
* Subscribes the given CompletableObserver to this CompletableSource instance.
* @param cs the CompletableObserver, not null
* @throws NullPointerException if {@code cs} is null
*/
void subscribe(CompletableObserver cs);
}
public interface CompletableObserver {
void onSubscribe(Disposable d);
void onComplete();
void onError(Throwable e);
}
从源码中我们可以看到CompletableObserver里面有三个接口,
1)onSubscribe中传入参数Disposable,由Completable调用一次,在CompletableObserver实例上设置Disposable,然后可以随时取消订阅。
2)onComplete一旦延迟计算正常完成将会被调用
3)onError 一旦延迟计算抛出异常将会被调用
4.2、Completable官网图解
图解说明
1)上面一副小图的意思是:一个Completable能发射一个onError或者一个onComplete消息,该消息会被CompletableObserver的onError或者onComplete接口接收到。
2)下面大图相对复杂,涉及到是否被阻断,也就是通过Disposable调用dispose()取消订阅,后面的消息无法接收。
4.3、Completable示例
可以运行一下下面的例子,可以看到在调用dispose后,onStart被回调后,后续的消息就收不到了;去掉dispose,onStart回调后,三秒后onComplete将会被回调
private void doCompletable() {
Disposable d = Completable.complete()
.delay(3, TimeUnit.SECONDS, Schedulers.io())
.subscribeWith(new DisposableCompletableObserver() {
@Override
public void onStart() {
System.out.println("Started");
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("onComplete!");
}
});
d.dispose();
}
运行完毕的结果是:
10-02 11:10:34.797 15565-15565/hq.demo.net I/System.out: Started
注释d.dispose()后在运行结果是:
10-02 14:34:19.490 23232-23232/hq.demo.net I/System.out: Started
10-02 14:34:22.492 23232-23483/hq.demo.net I/System.out: Done!
上面使用的是DisposableCompletableObserver通过subscribeWith来订阅消息,返回一个Disposable可以通过dispose来取消订阅关系,DisposableCompletableObserver是CompletableObserve的子类,只是增加了可取消订阅的功能。
当然也能通过一下方法操作,但是无法取消订阅关系,除此外没什么本质区别
private void doCompletable() {
Completable.complete()
.delay(3, TimeUnit.SECONDS, Schedulers.io())
.subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("Done!");
}
});
}
5、Maybe
5.1、Maybe简介
Maybe类表示延迟计算和单个值的发射,这个值可能根本没有或异常。
Maybe类实现MaybeSource的接口,MaybeObserver通过subscribe(MaybeObserver)在Maybe处订阅消息
Maybe遵循协议:onSubscribe (onSuccess | onError | onComplete),也就是Maybe发射消息后,可能会回调的接口是onSuccess | onError | onComplete
public abstract class Maybe<T> implements MaybeSource<T>
public interface MaybeSource<T> {
/**
* Subscribes the given MaybeObserver to this MaybeSource instance.
* @param observer the MaybeObserver, not null
* @throws NullPointerException if {@code observer} is null
*/
void subscribe(MaybeObserver<? super T> observer);
}
public interface MaybeObserver<T> {
void onSubscribe(Disposable d);
void onSuccess(T value);
void onError(Throwable e);
void onComplete();
}
5.2、Maybe官方图解
5.3、Maybe示例
下面是个例子,注意让线程睡多少秒可以修改测试dispose,与Completable类似,但是无论怎么onStart()都会被回调,为什么onStart()都会被回调呢可以看DisposableMaybeObserver源码,在订阅消息的时候就会首先回调onSubscribe,这个时候dispose还没有运行了,这个动作发生在订阅的时候,没有订阅何来取消订阅呢。
public abstract class DisposableMaybeObserver<T> implements MaybeObserver<T>, Disposable {
final AtomicReference<Disposable> s = new AtomicReference<Disposable>();
@Override
public final void onSubscribe(Disposable s) {
if (DisposableHelper.setOnce(this.s, s)) {
onStart();
}
}
/**
* Called once the single upstream Disposable is set via onSubscribe.
*/
protected void onStart() {
}
@Override
public final boolean isDisposed() {
return s.get() == DisposableHelper.DISPOSED;
}
@Override
public final void dispose() {
DisposableHelper.dispose(s);
}
}
下面是实例的运行和结果
private void doMaybe() {
new Thread(new Runnable() {
@Override
public void run() {
Disposable d = Maybe.just("Hello World")
.delay(3, TimeUnit.SECONDS, Schedulers.io())
.subscribeWith(new DisposableMaybeObserver<String>() {
@Override
public void onStart() {
System.out.println("Started");
}
@Override
public void onSuccess(String value) {
System.out.println("Success: " + value);
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("Done!");
}
});
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
d.dispose();
}
}).start();
}
运行结果是:
10-02 15:01:53.320 25573-25649/hq.demo.net I/System.out: Started
10-02 15:01:56.324 25573-25654/hq.demo.net I/System.out: Success: Hello World
如果把Thread.sleep(4000)修改为Thread.sleep(2000)运行结果是:
10-02 15:05:34.362 25840-25872/hq.demo.net I/System.out: Started
上面例子使用DisposableMaybeObserver通过subscribeWith在Maybe处订阅,并返回一个Disposable,可以通过Disposable调用dispose来取消订阅,当然我们也可以通过
下面的方式来完成,但是无法取消订阅关系
private void doMaybe() {
Maybe.just("Hello World")
.delay(3, TimeUnit.SECONDS, Schedulers.io())
.subscribe(new MaybeObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("Started");
}
@Override
public void onSuccess(String value) {
System.out.println("Success: " + value);
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("Done!");
}
});
}
6、总结:
Single、Completable、Maybe是简化的Observable,只是具有少部分功能
Single:只能发射一条单一数据或者一条异常通知,不能发射完成通知,数据与通知只能发射一个,二选一。
Completable:只能发射一条完成通知或者一条异常通知,不能发射数据,要么发射完成通知要么发射异常通,二选一。
Maybe:只能发射一条单一数据,和发射一条完成通知,或者一条异常通知,完成通知和异常通知二选一,只能在发射完成通知或异常通知之前发射数据,否则发射数据无效