文章目录
一、RxJava是什么?
RxJava:Reactive Extensions for the JVM.
A library for composing asynchronous and event-based programs by using observable sequences.
在我看来就是一个扩展了观察者模式的可以用于线程切换的流处理工具。
二、简单使用
1.引入库
io.reactivex.rxjava3:rxjava:3.1.7
io.reactivex.rxjava3:rxandroid:3.0.2
2.创建一个简单的Observable
Observable.create(object : ObservableOnSubscribe<String> {
override fun subscribe(emitter: ObservableEmitter<String>) {
emitter.onNext("data")
emitter.onComplete()
}
}).subscribe(object : Observer<String> {
override fun onSubscribe(d: Disposable) {
//获取 Disposable对象,用来终止订阅
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
Log.d("onComplete")
}
override fun onNext(t: String) {
Log.d("onNext:" + t)
}
})
三、知识点
1. Single、Observable、Maybe、Flowable、Completable
Single:发送单条数据
Observable:发送0条或多条数据,无背压策略
Maybe:发送0/1条数据
Flowable:发送0条或多条数据,且有背压策略
Completable:不发送数据
2. 观察者和被观察者是如何订阅的
以上面的过程为例,Observable.create()创建了一个Observable对象,通过实现Observer接口获得一个Observer对象,最后通过observable.subscribe(observer),使得Observable和Observer关联起来。其中最关键的是调用到了Observable的subscribeActural(observer)
@Override
protected void subscribeActual(Observer<? super T> observer) {
//创建发射器,并且把下游的observer给发射器
CreateEmitter<T> parent = new CreateEmitter<>(observer);
//给下游的observer添加被订阅的监听
observer.onSubscribe(parent);
try {
//给上游的ObservableOnSubscribe添加订阅
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
订阅是从下游的Observer向上游的Observable发送订阅,然后在订阅的过程中,给下游的Observer发送订阅监听Disposable,并且给上游的被观察者添加订阅。
3. RxJava是如何切换线程的
- subscribeOn()方法:返回ObservableSubscribeOn对象,是一个Observable,然后我们直接看关键代码
@Override
public void subscribeActual(final Observer<? super T> observer) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<>(observer);
//给下游的observer添加订阅的监听
observer.onSubscribe(parent);
//给SubscribeOnObserver设置disposable对象
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
然后我们看Scheduler的scheduleDirect
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
//创建Worker对象,跟踪源码可以看到Worker对象中包含了ScheduledExecutorService,
final Worker w = createWorker();
//钩子函数处理一下Runnable
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
//生成一个可销毁的DisposeTask对象
DisposeTask task = new DisposeTask(decoratedRun, w);
//跟踪源码是通过Worker内部的ScheduledExecutorService,开启新线程去执行Runnable
w.schedule(task, delay, unit);
return task;
}
而我们在ObservableSubscribeOn中传递进去的Runnable对象new SubscribeTask(parent)代码如下
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver<T> parent;
SubscribeTask(SubscribeOnObserver<T> parent) {
this.parent = parent;
}
@Override
public void run() {
//我们在新线程中开启了对上游的订阅,所以上游的所有操作都在新线程中
source.subscribe(parent);
}
}
- observerOn()方法:同理我们跟踪到ObservableObserveOn的subscribeActual()方法
@Override
protected void subscribeActual(Observer<? super T> observer) {
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
//创建Worker对象
Scheduler.Worker w = scheduler.createWorker();
//订阅上游,订阅者是ObserveOnObserver
source.subscribe(new ObserveOnObserver<>(observer, w, delayError, bufferSize));
}
}
然后我们跟踪ObserveOnObserver的onNext onComplete onError
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
//切线程
schedule();
}
@Override
public void onError(Throwable t) {
if (done) {
RxJavaPlugins.onError(t);
return;
}
error = t;
done = true;
//切线程
schedule();
}
@Override
public void onComplete() {
if (done) {
return;
}
done = true;
//切线程
schedule();
}
//切线程执行run方法
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
//在切换后的线程中执行
@Override
public void run() {
if (outputFused) {
drainFused();
} else {
drainNormal();
}
}
所以,在observerOn()方法后,ObserveOnObserver观察者在收到消息后,会在指定的线程中去执行。
4. subscribeOn()只有第一次有用?
根据知识点3中的讲解,我们知道在调用subscribeOn()后,上游的Observable都会在新线程中执行,所以当有多个subscribeOn()时,按照从下游Observer到上游Observable的订阅过程,后续生成的Observable会替代之前生成的Observable,因此只有第一次调用subscribeOn()的地方会最终决定被观察者发送数据的线程。但是后续调用的subscribeOn()确实也有切线程的作用,只不过切线程的作用范围仅到在它之前调用subscribeOn()之后。
5. observerOn()的作用范围
同理知识点4,每一次调用observerOn()的作用范围是截止到下一次调用observerOn()之前。
6. 背压
背压:上游产生数据的能力大于下游处理数据的能力
解决方案:1. 控制观察者接受事件的速度 使用subscrib.request() 2. 控制被观察者发送事件的速度 使用emitter.requested()
Rxjava2开始,Flowable支持添加背压策略,用来针对缓冲区,处理当缓存区大小存满、被观察者仍然继续发送下1个事件时,该如何处理
MISSING,//如果流的速度无法保持同步,可能会抛出MissingBackpressureException或IllegalStateException。
ERROR,//会在下游跟不上速度时抛出MissingBackpressureException。
BUFFER,//上游不断的发出onNext请求,直到下游处理完,也就是和Observable一样了,缓存池无限大,最后直到程序崩溃
DROP,//会在下游跟不上速度时把onNext的值丢弃。
LATEST//会一直保留最新的onNext的值,直到被下游消费掉。
7. RxJava的操作符
(1). 创建类
- create() // 创建
- just() // 直接发送
- fromArray() // 直接发送数组
- fromIterable() // 直接发送结合
- empty() // 仅发送complete
- error() // 仅发送error
- never() // 不发送
- timer() // 定时发送
- interval() // 周期性发送
(2). 操作类
- map() // 对数据进行类型转换
- flatMap() // 将一个Observable转换成多个Observables,然后将发射的数据合并到一个单独的Observable,但数据是无序的
- concatMap() // 将一个Observable转换成多个Observables,然后将发射的数据合并到一个单独的Observable,但数据是有序的
- buffer() // 定期从 被观察者(Obervable)需要发送的事件中 获取一定数量的事件并放到缓存区中,最终发送
- concat()、concatArray() // 组合多个被观察者,合并后按发送顺序串行执行
- merge()、mergeArray() // 组合多个被观察者,合并后按时间线并行执行
- zip() // 合并两个Observable发射的事件,根据BiFunction函数生成一个新的值发射出去
- reduce() // 把被观察者需要发送的事件聚合成1个事件并发送
- startWith()/startWithArray() // 在一个被观察者发送事件前,追加发送一些数据 / 一个新的被观察者
- count() // 统计被观察者发送事件的数量
- filter() // 过滤被观察者发送的事件,如果返回true则发送事件,否则不会发送
- ofType() // 过滤一个Observable只返回指定类型的数据
- skip() // 忽略Observable’发射的前N项数据,只保留之后的数据
- skipLast() // 从结尾往前数跳过制定数量的事件
- distinct() // 过滤事件序列中重复的事件
- distinctUntilChanged() // 过滤事件序列中连续重复的事件
- take() // 只发送前N个数据
- takeLast() // 发射最后N个数据
- throttleFirst() // 规定时间段内只发送第一个数
- throttleLast() // 规定时间段内只发送最后一个数
- sample() // 规定段时间内,只发送该段时间内最新(最后)1次事件,和 throttleLast()一样
- debounce() // 发送数据事件时,若2次发送事件的间隔<指定时间,就会丢弃前一次的数据,直到指定时间内都没有新数据发射时才会发送后一次的数据
- firstElement() // 仅选取第一个元素
- lastElement() // 仅选取最后一个元素
- elementAt() // 指定接收某个元素,如果越界不发送数据,不报错
- elementAtOrError() // 指定位置如果越界,报错
- delay() // 被观察者延迟一段时间在发送事件
- do()系列 // 在某个事件的生命周期中调用
- onErrorReturn() // 遇到错误时,发送该事件并正常终止
- onErrorResumeNext() // 遇到Throwable时,发送1个新的Observable
- onExceptionResumeNext() // 遇到Exception时,发送1个新的Observable
- retry() // 出现错误时,让被观察者(Observable)重新发射数据
- retryUntil() // 出现错误后,判断是否需要重新发送数据,返回 true 则不重新发送数据事件,否则重新发送该Observable
- retryWhen() // 遇到错误时,将发生的错误传递给一个新的被观察者(newObservable),并决定是否需要重新订阅原始被观察者(Observable)并发送事件
- repeat() // 无条件地、重复发送 被观察者事件
- repeatWhen() // 有条件地、重复发送 被观察者事件
- all() // 判定是否Observable发射的所有数据都满足某个条件
- takeWhile() // 发射Observable发射的数据,直到一个指定的条件不成立
- skipWhile() // 跳过Observable发射的数据,直到一个指定的条件不成立
- takeUntil() // 执行到某个条件时,停止发送事件 / 执行到下一个Observable开始发送数据时停止发送
- skipUntil() // 等到 skipUntil() 传入的Observable开始发送数据,(原始)第1个Observable的数据才开始发送数据
- SequenceEqual() // 判定两个Observables是否发射相同的数据序列。若相同,返回 true;否则,返回 false
- contains() // 判断发送的数据中是否包含指定数据
- isEmpty() // 判断发送的数据是否为空
- amb() // 当需要发送多个 Observable时,只发送 先发送数据的Observable的数据,而其余 Observable则被丢弃。
- defaultIfEmpty() // 在不发送任何有效事件( Next事件)、仅发送了 Complete 事件的前提下,发送一个默认值