什么是RxJava?
RxJava在GitHub上《RxJava》的自我介绍是:a library for composing asynchronous and event-based programs using observable sequences for the Java VM.(一个在Java VM 上使用可观测的序列来组成异步的,基于事件的程序的库),有些人可能感到疑惑,其实本质上可以用一词来概括——“异步”,它就是一个异步的操作库,而别的定语都基于这之上。
RxJava的优点是什么?
简洁。随着程序代码逻辑的变得越来越复杂,它依然使得异步操作保持简洁。实现优雅:RxJava的使用方式是基于事件流的链式调用。
RxJava的观察者模式:
RxJava有四个基本概念:Observer(观察者),Observable(被观察者),subscribe(订阅),事件。Observer和Observable通过subscribe()实现订阅关系,从而Observable可以在需要的时候发出事件通知Observer。
- Observer:观察者,他决定事件发生时有怎么样的行为。
- Observable:被观察者,他决定什么时候触发事件以及触发什么样的事件。
- subscribe:订阅,将Observer和Observable关联起来。
RxJava具体使用步骤:
1.创建被观察者Observable:
它决定什么时候触发事件以及触发怎么样的事件,通过Observable.create(ObservableOnSubscribe)创建被观察者实例,这是最基本的创造事件序列的方法,并为它定义事件触发规则。
//创建被观察者Observable
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("RxJava:e.onNext== 第一次");
e.onNext("RxJava:e.onNext== 第二次");
e.onNext("RxJava:e.onNext== 第三次");
e.onComplete();
}
});
创建一个ObservableOnSubscribe对象并且实现subscribe()方法,设定了事件的内容是String,并返回ObservableEmitter,相当于一个计划表,当Observable被订阅的时候,复写subscribe()方法定义发送的事件,ObservableEmitter是事件发射器,定义并且向观察者发送需要发送的事件,onNext()会被执行三次,最后执行onComplete()方法,这样由被观察者调用观察者回调的方法,实现了被观察者向观察者传递事件。
2.创建观察者Observer:
它决定事件触发有怎样的行为,定义响应事件的行为,直接new一个Observer观察者实例,实现其中相应的方法:
//创建观察者Observer
Observer<String> observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG, "onSubscribe == 订阅");
}
@Override
public void onNext(String s) {
Log.e(TAG, "onNext == " + s);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError == " + e.getMessage());
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete == ");
}
};
- onSubscribe(Disposable d):事件订阅成功回调,返回Disposable请求实例,可以通过d.dispose()取消请求;
- onNext(T): 响应事件的方法,发送事件时,观察者会回调onNext()方法,接收事件数据;
- onError(): 事件队列异常,在处理事件出现异常的时候回触发这个方法,其他事件不会再继续发出;
- onComplete():事件队列完结,当不再有新onNext()发出时,需要触发onComplete()方法来作为标志,其他事件不会再继续发出。
在一个正确的事件运行队列中,onError()和onComplete()有且仅有一个出现,并且是在事件的最后出现,即onError()和onComplete()是互斥的,当一个出现了,另一个就不会再出现。
3.subscribe()
订阅,连接Observable(被观察者)和Observer(观察者)。
//订阅(观察者观察被观察者)
observable.subscribe(observer);
Observable是被观察者,observer是观察者,创建完Observer和Observable之后,通过subscribe()将两者关联起来。
通过该调用,回调观察者的相关方法,从而响应被观察者响应的事件,Observable只生产事件,真正发送事件的是在它订阅的时候,即subscribe()被调用的时候。
另外:被观察者Observable的subscribe具有多个重载的方法:
//观察者不对被观察者发送的事件做出响应(但是被观察者还可以继续发送事件)
public final Disposable subscribe()
//观察者对被观察者发送的任何事件都做出响应
public final void subscribe(Observer<? super T> observer)
//表示观察者只对被观察者发送的Next事件做出响应
public final Disposable subscribe(Consumer<? super T> onNext)
//表示观察者只对被观察者发送的Next & Error事件做出响应
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError)
//表示观察者只对被观察者发送的Next & Error & Complete事件做出响应
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
Action onComplete)
//表示观察者只对被观察者发送的Next & Error & Complete & onSubscribe事件做出响应
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
Action onComplete, Consumer<? super Disposable> onSubscribe)
Scheduler调度者:
在RxJava默认规则中,事件的发出和消费都是在同一个线程中发生的,那么上面的例子来说,就是一个同步的观察者模式。观察者模式的本身就是后台处理,前台回调的异步机制,因此异步对RxJava来说是至关重要的,异步的实现则需要用到Scheduler调度器来切换线程。
在RxJava中Scheduler(调度器)相当于线程控制器,RxJava通过Scheduler来指定那一部分代码执行在哪一个线程。我们来看看简单的例子:
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("RxJava:e.onNext== 第一次");
e.onComplete();
Log.d(TAG, "subscribe()线程==" + Thread.currentThread().getId());
}
}).subscribeOn(Schedulers.io())//指定被观察者subscribe()(发送事件的线程)在IO线程()
.observeOn(AndroidSchedulers.mainThread());//指定观察者接收响应事件的线程在主线程。
- subscribeOn():用于指定Observable被观察者subscribe()时所发生的线程,即指定发生事件的线程。
- observeOn():指定Observer观察者接收和相应事件的线程,即订阅者接收事件的线程。
注意:多次指定发射事件的线程只有第一次指定有效,也就是说多次调用subscribeOn()只有第一次有效,其余的会被忽略;但是多次指定订阅者接收事件的线程是可以的,也就是说每observeOn()一次,接收事件的线程就会切换一次。
RxJava中内置了很多线程项供我们选择:
- Schedulers.io():代表IO操作的线程,通常用于网络、读写文件等IO密集型的操作。行为模式和new Thread()差不多,只是IO的内部是一个无上限的线程池,可复用空闲的线程,更高效(不要把计算工作放在IO内,可以避免创建不必要的线程)。
- AndroidSchedulers.mainThread():Android的主线程,用于更新UI。
- Schedulers.newThread():总是启用新线程,并在新线程中执行操作;多用于耗时操作。
- Schedulers.computation():代表CPU计算密集型的操作,即不会被IO等操作限制性能的操作。
快速创建Observable被观察者操作符:
1.create():
是所有创建型操作符的“根”,也就是说其他创建型操作符最后都是通过create()来创建的Observable的,快速创建被观察者对象。
2.empty():
快速创建被观察者对象,仅发送onComplete()事件,直接通知完成。
3.error():
快速创建被观察者对象,仅发送onError()事件,直接通知异常。
4.never():
快速创建被观察者对象,不发送任何事件。
5.just(T...items):
快速创建被观察者对象,最多只能发送10个事件。
6.fromArray(T...items):
快速创建被观察者对象,可发送多个任意子类型的数据。
延迟创建Observable被观察者操作符:
1.defer():
直到有Observer观察者订阅时,才会通过Observeable的工厂方法动态创建Observeable,并且发送事件,每次订阅后都会得到一个刚创建的最新的Observable对象,确保被观察者对象的数据是最新的。
2.timer():
快速创建Observable被观察者对象,延迟指定时间后发送一个类型为Long的事件。
构造方法:
timer(long delay, TimeUnit unit)
timer(long delay, TimeUnit unit, Scheduler scheduler)
- delay:延时的时间,类型为Long。
- unit:表示时间单位,有TimeUnit.SECONDS等多种类型。
- scheduler:表示调度器,用于指定线程。
3.interval():
快速创建Observable被观察者对象,每隔指定的时间就发送相应的事件,事件序列从0开始,无限递增1。
构造方法:
//在指定延迟时间后,每隔多少时间发送一次事件
interval(long initialDelay, long period, TimeUnit unit)
//在指定的延迟时间后,每隔多少时间发送一次事件,可以指定调度器
interval(long initialDelay, long period, TimeUnit unit, Scheduler scheduler)
//每间隔多少时间发送一次事件,使用默认的线程
Observable<Long> interval(long period, TimeUnit unit)
//每间隔多少时间发送一次事件,可以指定调度器
interval(long period, TimeUnit unit, Scheduler scheduler)
- initialDelay:表示延迟开始的时间,类型为Long。
- period:距离下一次发送事件的时间间隔,类型为Long。
- unit:表示时间单位,有TimeUnit.SECONDS等多种类型。
- scheduler:表示调度器,用于指定线程。
4.intervalRange():
类似于interval(),快速创建一个被观察者对象,指定时间间隔就发送事件,可以执行发送事件的数量,数据依次递增1。
构造方法:
intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit)
intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit, Scheduler scheduler)
- start:表示事件开始的数值大小,类型为Long。
- count:表示事件执行的次数,类型为long,不能为负数。
- initialDelay:表示延迟开始的时间,类型为Long。
- period:距离下一次发送事件的时间间隔,类型为Long。
- unit:时间单位,有TimeUnit.SECONDS等多种类型。
- scheduler:表示调度器,用于指定线程。
注意:count不能为负数,否则会抛出异常。
5.range(final int start,final int count):
类似于intervalRange(),快速创建一个被观察者对象,指定事件起始值,执行发送事件的数量,但是区别在于range()不能延迟发送的时间。
注意:上述参数的类型是int类型,rangeLong(long start, long count)只是参数类型不同,用法一致。
上述几种常用的创建操作符比较总结:
Observable被观察者变换操作符:
1.map():
map操作符把被观察者Observable产生的结果通过映射规则转换成另一种结果集,并交给订阅者处理。简单来说就是对被观察者发送的每个事件都通过指定函数的处理,从而转变成另一种事件。
2.flatMap():
flatMap()
: 这是一个很有用但非常难理解的变换,因此我决定花多些篇幅来介绍它。 首先假设这么一种需求:假设有一个数据结构『学生』,现在需要打印出一组学生的名字。实现方式很简单:
Student[] students = ...;
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onNext(String name) {
Log.d(tag, name);
}
...
};
Observable.from(students)
.map(new Func1<Student, String>() {
@Override
public String call(Student student) {
return student.getName();
}
})
.subscribe(subscriber);
很简单。那么再假设:如果要打印出每个学生所需要修的所有课程的名称呢?(需求的区别在于,每个学生只有一个名字,但却有多个课程。)首先可以这样实现:
Student[] students = ...;
Subscriber<Student> subscriber = new Subscriber<Student>() {
@Override
public void onNext(Student student) {
List<Course> courses = student.getCourses();
for (int i = 0; i < courses.size(); i++) {
Course course = courses.get(i);
Log.d(tag, course.getName());
}
}
...
};
Observable.from(students)
.subscribe(subscriber);
依然很简单。那么如果我不想在 Subscriber
中使用 for 循环,而是希望 Subscriber
中直接传入单个的 Course
对象呢(这对于代码复用很重要)?用 map()
显然是不行的,因为 map()
是一对一的转化,而我现在的要求是一对多的转化。那怎么才能把一个 Student 转化成多个 Course 呢?
这个时候,就需要用 flatMap()
了:
Student[] students = ...;
Subscriber<Course> subscriber = new Subscriber<Course>() {
@Override
public void onNext(Course course) {
Log.d(tag, course.getName());
}
...
};
Observable.from(students)
.flatMap(new Func1<Student, Observable<Course>>() {
@Override
public Observable<Course> call(Student student) {
return Observable.from(student.getCourses());
}
})
.subscribe(subscriber);
从上面的代码可以看出, flatMap()
和 map()
有一个相同点:它也是把传入的参数转化之后返回另一个对象。但需要注意,和 map()
不同的是, flatMap()
中返回的是个 Observable
对象,并且这个 Observable
对象并不是被直接发送到了 Subscriber
的回调方法中。 flatMap()
的原理是这样的:1. 使用传入的事件对象创建一个 Observable
对象;2. 并不发送这个 Observable
, 而是将它激活,于是它开始发送事件;3. 每一个创建出来的 Observable
发送的事件,都被汇入同一个 Observable
,而这个 Observable
负责将这些事件统一交给 Subscriber
的回调方法。这三个步骤,把事件拆成了两级,通过一组新创建的 Observable
将初始的对象『铺平』之后通过统一路径分发了下去。而这个『铺平』就是 flatMap()
所谓的 flat。
flatMap()
示意图:
flatMap()操作符是将Observable(被观察者)产生的结果拆分和单独转换变成多个Observable,然后把多个Observable“扁平化”整合成新的一个Observable,并依次提交产生的结果给订阅者。大意为:flatMap()通过传入一个函数作为参数转换源Observable(被观察者),在这个函数中你可以自定义转换规则,最后在这个函数中返回一个新的Observable,然后flatMap函数回调方法通过合并这些Observable成一个新的Observable,发送给Observer(观察者)。(理论比较抽象,我们来看例子)
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) {
e.onNext("A");
e.onNext("B");
e.onComplete();
}
}).flatMap(new Function<String, ObservableSource<String>>() {
@Override//通过flatMap将被观察者生产的事件进行拆分,再将新的事件转换成一个新的Observable发送
public ObservableSource<String> apply(String s) {
List<String> list = new ArrayList<>();
Log.e(TAG, "flatMap:apply == 事件" + s);
//将一个事件拆分成两个子事件,例如将A事件拆分成A0,A1两个事件,然后再整个合成一个Observable通过fromIterable发送给订阅者
for (int j = 0; j < 2; j++) {
list.add("拆分后的子事件" + s + j);
}
return Observable.fromIterable(list);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) {
Log.e(TAG, "flatMap:accept == " + s);
}
});
上面我们发送了A、B两个事件,在flatMap中接收到A事件后,将A事件拆分成A0,A1两个事件,再通过fromIterable(list)整合成一个Observable发送给订阅者。打印log如下:
注意:flatMap在合并Observable结果时,可能存在交叉的情况出现,即新合并生成的序列可能是无序的。
3.concatMap():
concatMap()和flatMap()方法类似,都是把Observable(被观察者)产生的事件转换成多个Observable(被观察者),然后把Observable整合成一个Observable,并依次提交生产的结果给订阅者。与flatMap()不同的是,concatMap()在处理产生的Observable时,采用的是“连接concat”的方式,而不是“marge合并”的方式,这样就保证了产生事件的顺序性,也就是说提交给订阅者的结果是按照顺序提交的,不会存在交叉的可能性。
4.buffer():
buffer()操作符将Observable(被观察者)需要发送的事件周期性收集到列表中,并把这列表提交给Observer(观察者),观察者处理后,清空buffer列表,同时接收下一次的结果交给订阅者,周而复始。需要注意的是:一但初始的Observable在产生事件中出现异常,即使buffer()收集到已经存在的结果,订阅者也会马上收到这个异常,并结束整个过程。
变换操作符比较总结:
组合操作符:
1.concat()和concatArray():
concat()与concatArray()都是组合多个被观察者的一起发送数据,合并后安先后顺序执行。
二者的区别是:concat()的观察者数量最多是4个,而concatArray()的个数没有限制。
//concat的构造方法
concat(source1);
concat(source1, source2);
concat(source1, source2, source3);
concat(source1, source2, source3, source4);
//concatArray的构造方法
concatArray(ObservableSource<? extends T>... sources);
2.merge()和mergeArray():
Merge()与MergeArray()组合多个被观察者发送数据,按照时间先后顺序来执行。与concat()与concatArray()组合类似。
Merge()与MergeArray()的区别:Merge()只能发送最多4个Observable(被观察者),MergeArray()的数量没有限制。都是按照时间的先后顺序来执行被观察者发送事件。
3.concatDelayError():
concat()与concatArray()组合中,如果某一个Observable(被观察者)发出onError()事件,则会马上停止其他事件的发送。如果需要onError()事件推迟到其他事件发送完成才出发的话则需要用到concatDelayError()方法。
4.megreDelayError():
megreDelayError()方法同上,meger()合并的某个Observable(被观察者)出现异常,会马上停止合并,并对订阅者回到onError()方法,而megreDelayError()会把错误在所有结果合并完后才执行。
5.startWith()与startWithArray():
startWith()与startWithArray()操作符都是在源Observable(被观察者)提交结果之前,插入指定的某些数据,注意调用顺序:先调用最后加入的数据。
ArrayList<String> strings = new ArrayList<>();
strings.add("Array:1");
Observable.just("一", "二", "三", "四")
.startWith(strings)//插入单个集合
.startWith("startWith:2")//插入单个数据
.startWithArray("startWithArray:3", "startWithArray:4")//插入多个数据
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG, "startWith:onSubscribe == 订阅");
}
@Override
public void onNext(String s) {
Log.e(TAG, "startWith:onNext 结果== " + s);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "startWith:onError == " + e.getMessage());
}
@Override
public void onComplete() {
Log.e(TAG, "startWith:onComplete == ");
}
});
上面例子中,在just()的前面依次加入的是:集合[Array:1],“startWith:2”,"startWithArray:3", "startWithArray:4",但是打印出来的结果顺序却刚好相反,说明Observable优先发送最后插入的数据,log如下:
组合操作符比较总结:
合并操作符:
1.zip():
zip()是把两个Observable(被观察者)提交的结果,严格按照顺序对位进行合并,最后发送给订阅者,最终合并的数量等于多个Observable数量最少的数量。
注意:下面的Observable1中的4并没有事件与其合并打印出来,但是事件还是会发送的。
//设置需要传入的被观察者数据
Observable<Integer> observable1 = Observable.just(1, 2, 3, 4);
Observable<String> observable2 = Observable.just("A", "B", "C");
//回调apply()方法,并在里面自定义合并结果的逻辑
// BiFunction<Integer, String, String>,第一个类型为observable1的参数类型,第二个类型为observable2的参数类型,第三个为合并后的参数类型
Observable.zip(observable1, observable2, new BiFunction<Integer, String, String>() {
@Override
public String apply(Integer integer, String str) throws Exception {
return integer + str;
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG, "zip:onSubscribe == 订阅");
}
@Override
public void onNext(String s) {
Log.e(TAG, "zip:onNext == " + s);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "zip:onError == " + e.getMessage());
}
@Override
public void onComplete() {
Log.e(TAG, "zip:onComplete == ");
}
});
上面根据顺序的对位合并数据为:1A,2B,3C,4没有与其合并的事件,打印log如下:
2.combineLatest():
combineLatest()是将两个Observable(被观察者)产生的结果进行合并,合并的结果将组成一个新的Observable发送给订阅者。这两个Observable中任意的一个Observable产生的结果,都与另一个Observable最后的结果,按照一定的规则进行合并。
与zip()类似,区别在于zip()根据个数1对1合并,combineLatest()根据时间点一对一合并。
//产生0,10,20的事件序列,每隔1秒发送事件,一共发送3次
Observable<Long> observable1 = Observable.interval(0, 1, TimeUnit.SECONDS)
.map(new Function<Long, Long>() {
@Override
public Long apply(Long aLong) throws Exception {
return aLong * 10;
}
}).take(3);
//产生0,1,2,3,4的事件序列,起始值为0,一共发送4次,延迟1秒后开始发送,每隔1秒发送事件
Observable<Long> observable2 = Observable.intervalRange(0, 4, 1, 1, TimeUnit.SECONDS)
.map(new Function<Long, Long>() {
@Override
public Long apply(Long aLong) throws Exception {
return aLong * 1;
}
});
Observable.combineLatest(observable1, observable2, new BiFunction<Long, Long, Long>() {
@Override
public Long apply(Long o1, Long o2) throws Exception {
Log.e(TAG, "combineLatest:apply: o1+o2:" + o1 + "+" + o2);
//observable1的最后的一个数据都与observable2的每一个数据相加
return o1 + o2;
}
}).subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG, "combineLatest:onSubscribe == 订阅");
}
@Override
public void onNext(Long aLong) {
Log.e(TAG, "combineLatest:onNext 合并的结果== " + aLong);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "combineLatest:onError == " + e.getMessage());
}
@Override
public void onComplete() {
Log.e(TAG, "combineLatest:onComplete == ");
}
});
Observable1的事件序列为0,10,20;Observable2的事件序列为0,1,2,3, Observable2因为延迟了1秒发送,所以在Observable1执行1秒后即Observable1=10时,Observable2才开始执行事件,否则在Observable2未开始执行事件前,Observable2的默认值与Observable1合并事件,如果Observable1执行完事件后,以Observable1最后的值为准Observable1=20,那么合并出来的数据为:10+0,20+0,20+1,20+2,20+3,打印log如下:
3.combineLatestDelayError():
combineLatest()合并过程中一但出现异常就会立即停止后续合并事件,并且回调onError()方法,combineLatestDelayError()是把错误放到所有结果都合并完成之后才执行。combineLatestDelayError()类似concatDelayError()、mergeDelayError(),这里就不在举例子了。
4.reduce():
reduce()把观察者需要发送的事件聚合成一个事件并且发送。本质上都是前两个数据聚合,再与后一个数据聚合,依次类推。
Observable.just(1, 2, 3, 4, 5).
reduce(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) throws Exception {
Log.e(TAG, "reduce:accept 计算结果== " + integer + "*" + integer2);
//按先后顺序,两个事件聚合处理后 ,将结果再与下一事件聚合处理,依次类推
return integer * integer2;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.e(TAG, "reduce:accept 合并的结果== " + integer);
}
});
比如上面的1, 2, 3, 4, 5共5个事件,1与2聚合后生成新的Observable(被观察者),新的Observable与下一个数3再聚合,依次类推,所以数据聚合完成,打印数据如下:
5.collect():
将Observable(被观察者)发送的数据收集到一个容器中(数据结构)。Observable将事件队列分别装入一个准备好的容器中,然后在新的Observable将该容器发送给订阅者。
//第一个参数:声明容器的类型,第二个参数:处理数据的逻辑,加入容器中
Observable.just(1, 2, 3, 4, 5).collect(new Callable<ArrayList<Integer>>() {
@Override
public ArrayList<Integer> call() throws Exception {
return new ArrayList<>();
}
}, new BiConsumer<ArrayList<Integer>, Integer>() {
@Override
public void accept(ArrayList<Integer> list, Integer integer) throws Exception {
Log.e(TAG, "reduce:collect 加入容器的数据== " + integer);
list.add(integer);
}
}).subscribe(new Consumer<ArrayList<Integer>>() {
@Override
public void accept(ArrayList<Integer> integers) throws Exception {
Log.e(TAG, "reduce:collect 最后结果== " + integers);
}
});
Callable方法声明一个容器,Callable实现的方法将数据加入容器中,打印数据如下:
合并操作符比较总结:
统计发送事件的数量:
1.count():
count()方法是统计Observable(被观察者)发送的事件的数量。
RxJava之四种Subject:
subject是将观察者和被观察者结合为一体,是观察者和被观察者的代理。
1.AsyncSubject:
AsyncSubject asyncSubject = AsyncSubject.create();
asyncSubject.onNext("A");
asyncSubject.onNext("B");
asyncSubject.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 {
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("执行完成!");
}
});
asyncSubject.onNext("C");
asyncSubject.onComplete();
日志如下:
也就是说,AsyncSubject 无论发射多少条数据,无论在订阅前发射还是在订阅后发射,都只会收到最后一条发射的数据。
2.BehaviorSubject:
BehaviorSubject behaviorSubject = BehaviorSubject.create();
behaviorSubject.onNext("A");
behaviorSubject.onNext("B");
behaviorSubject.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 {
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("执行完成!");
}
});
behaviorSubject.onNext("C");
behaviorSubject.onComplete();
日志如下:
也就是说,BehaviorSubjec只会接收到订阅前最后一条发射的数据以及订阅之后所有的数据。
3.ReplaySubject:
ReplaySubject replaySubject = ReplaySubject.create();
replaySubject.onNext("A");
replaySubject.onNext("B");
replaySubject.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 {
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("执行完成!");
}
});
replaySubject.onNext("C");
replaySubject.onComplete();
日志如下:
也就是说,ReplaySubject会接收到全部数据。
这里需要补充一下:ReplaySubject可以限制缓存的大小,也可以限制缓存的时间。
ReplaySubject replaySubject = ReplaySubject.createWithSize(1);
ReplaySubject replaySubject = ReplaySubject.createWithTime(1000, TimeUnit.MILLISECONDS, Schedulers.newThread());
ReplaySubject replaySubject = ReplaySubject.createWithTimeAndSize(1000, TimeUnit.MILLISECONDS, Schedulers.newThread(), 1);
- createWithSize 限制可以接收订阅前发射数据的条数;
- createWithTime 限制时间内可以接收订阅前发射的数据;
- createWithTimeAndSize 限制时间内可以接收订阅前发射数据的条数;
4.PublishSubject:
PublishSubject publishSubject = PublishSubject.create();
publishSubject.onNext("A");
publishSubject.onNext("B");
publishSubject.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 {
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("执行完成!");
}
});
publishSubject.onNext("C");
publishSubject.onComplete();
日志如下:
也就是说,PublishSubject只会接收到订阅之后的所有数据。