前言
Rxjava2从使用者角度来说,可以从观察者订阅被观察者理解,被观察者可以进行类型转换,即操作符运算,被观察者和观察者可以在指定线程上操作,即异步。
Rxjava2的核心是异步和操作符(数据流)运算。
从源码角度来说,个人感觉从责任链模式角度理解当前Rxjava2架构比观察者模式更加合适。
demo
Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull FlowableEmitter<String> emitter) throws Exception {
emitter.onNext("1");
emitter.onNext("2");
emitter.onNext("3");
emitter.onComplete();
}
}, BackpressureStrategy.ERROR)
.map(new Function<String, String>() {
@Override
public String apply(@androidx.annotation.NonNull String s) throws Exception {
return "中间做了转换:" + s;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
//一次性接受数据的最大个数,当前数据如果不设置,那么将不会接受到数据
s.request(3);
}
@Override
public void onNext(String user) {
Timber.d("tag:" + user);
}
@Override
public void onError(Throwable t) {
Timber.d("tag错误:" + t);
}
@Override
public void onComplete() {
Timber.d("tag完成:");
}
});
简单解读
-
使用发射器发射数据:
emitter.onNext("1"); emitter.onNext("2"); emitter.onNext("3"); emitter.onComplete(); -
使用一个转换器将数据做了加工(操作符):
new Function<String, String>() { @Override public String apply(@androidx.annotation.NonNull String s) throws Exception { return "中间做了转换:" + s; } } -
发射数据加工过的新数据(如果没有第二步,这里表示发射的数据)指定执行线程:
.subscribeOn(Schedulers.io()) -
指定接收数据线程:
.observeOn(AndroidSchedulers.mainThread()) -
接收数据:
new Subscriber<String>() { @Override public void onSubscribe(Subscription s) { s.request(3); } @Override public void onNext(String user) { Timber.d("tag:" + user); } @Override public void onError(Throwable t) { Timber.d("tag错误:" + t); } @Override public void onComplete() { Timber.d("tag完成:"); } }
Rxjava2从责任链模式理解架构
架构设计
-
定义一个发射器接口,用于发射数据、发射完成、发射异常处理;
-
定义一个被订阅者接口,当前接口订阅一个发射器:该发射器用于发射数据;
-
定义一个订阅者接口,接受被订阅者或者上一个订阅者传递过来的数据;
-
定义一个基类处理器(下面所有处理器都继承当前处理器);
-
定义一个处理器,当前处理器用于①创建发射器,②创建的发射器交给被订阅者(用于发射数据、发射完毕、发射异常处理);③将传递过来的下游订阅者作为参数传递给发射器,发射器发射数据/发射完毕/发射异常的同时通知下游订阅者;
-
定义一个处理器,用于指定线程处理上游订阅者;
-
定义一个处理器,指定线程处理下游订阅者;
代码实现
-
定义一个发射器接口,用于发射数据、发射完成、发射异常处理;
public interface Emitter<T> { void onNext(@NonNull T value); void onError(@NonNull Throwable error); void onComplete(); } -
定义一个被订阅者接口,当前接口订阅一个发射器:该发射器用于发射数据;
public interface FlowableOnSubscribe<T> { void subscribe(@NonNull FlowableEmitter<T> emitter) throws Exception; } -
定义一个订阅者接口,接受被订阅者或者上一个订阅者传递过来的数据;
public interface Subscriber<T> { //该方法用于传递当前对象(作为上游对象)传递给下游处理器, public void onSubscribe(Subscription s); public void onNext(T t); public void onError(Throwable t); public void onComplete(); } -
定义一个基类处理器(下面所有处理器都继承当前处理器);
public abstract class Flowable<T> implements Publisher<T> { //定义一个创建发射器的处理器 public static <T> Flowable<T> create(FlowableOnSubscribe<T> source, BackpressureStrategy mode) { ObjectHelper.requireNonNull(source, "source is null"); ObjectHelper.requireNonNull(mode, "mode is null"); return new FlowableCreate<T>(source, mode); } //数据流转换-后面会讲到 public final <R> Flowable<R> map(Function<? super T, ? extends R> mapper) { ObjectHelper.requireNonNull(mapper, "mapper is null"); return new FlowableMap<T, R>(this, mapper); } //上游的数据在指定线程上执行 public final Flowable<T> subscribeOn(@NonNull Scheduler scheduler, boolean requestOn) { ObjectHelper.requireNonNull(scheduler, "scheduler is null"); return new FlowableSubscribeOn<T>(this, scheduler, requestOn); } //下游订阅者对象在指定线程上执行:指定方法,因为某些方法不需要在指定线程处理。 public final Flowable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) { ObjectHelper.requireNonNull(scheduler, "scheduler is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return new FlowableObserveOn<T>(this, scheduler, delayError, bufferSize); } //解决背压问题-后面会讲到 @Override public final void subscribe(Subscriber<? super T> s) { ObjectHelper.requireNonNull(s, "s is null"); subscribeActual(new StrictSubscriber<T>(s)); } //将下游对象传递给当前处理器 protected abstract void subscribeActual(Subscriber<? super T> s); } -
定义一个处理器,当前处理器用于①创建发射器,②创建的发射器交给被订阅者(用于发射数据、发射完毕、发射异常处理);③将传递过来的下游订阅者作为参数传递给发射器,发射器发射数据/发射完毕/发射异常的同时通知下游订阅者;
public final class FlowableCreate<T> extends Flowable<T> { final FlowableOnSubscribe<T> source; public FlowableCreate(FlowableOnSubscribe<T> source) { this.source = source; } @Override public void subscribeActual(Subscriber<? super T> t) { //1.创建发射器,并且将下游订阅者对象传递给发射器,发射器方法调用时传递给下游订阅者方法 BaseEmitter<T> emitter = new BaseEmitter<T>(t); //2.当前发射器作为上游对象传递给下游订阅者 t.onSubscribe(emitter); try { //发射器对象传递给并订阅者,被订阅者使用当前发射器发射数据 source.subscribe(emitter); } catch (Throwable ex) { Exceptions.throwIfFatal(ex); emitter.onError(ex); } static class BaseEmitter<T> extends AtomicLong implements FlowableEmitter<T>, Subscription { private static final long serialVersionUID = 7326289992464377023L; final Subscriber<? super T> downstream; final SequentialDisposable serial; BaseEmitter(Subscriber<? super T> downstream) { this.downstream = downstream; this.serial = new SequentialDisposable(); } } @Override onNext(T t){ downstream.onNext(t) } @Override public void onComplete() { downstream.onComplete() } @Override public void onError(){ downstream.onError(); } } } -
定义一个处理器,用于指定线程处理上游订阅者:以下代码相对来说比较简单,我就直接全部贴出来了,
public final class FlowableSubscribeOn<T> extends Flowable<T> { /** * The upstream source Publisher. */ protected final Flowable<T> source; final Scheduler scheduler; final boolean nonScheduledRequests; public FlowableSubscribeOn(Flowable<T> source, Scheduler scheduler, boolean nonScheduledRequests) { super(source); this.scheduler = scheduler; this.source = source; this.nonScheduledRequests = nonScheduledRequests; } @Override public void subscribeActual(final Subscriber<? super T> s) { Scheduler.Worker w = scheduler.createWorker(); //创建一个订阅者对象,将上一个处理器传递(上游订阅者)的对象作为参数 final SubscribeOnSubscriber<T> sos = new SubscribeOnSubscriber<T>(s, w, source, nonScheduledRequests); //将当前SubscribeOnSubscriber对象作为上游订阅者传递给下一个处理器 s.onSubscribe(sos); //其实就是执行SubscribeOnSubscriber的run方法,表示指定线程处理SubscribeOnSubscriber w.schedule(sos); } static final class SubscribeOnSubscriber<T> extends AtomicReference<Thread> implements FlowableSubscriber<T>, Subscription, Runnable { private static final long serialVersionUID = 8094547886072529208L; final Subscriber<? super T> downstream; final Scheduler.Worker worker; final AtomicReference<Subscription> upstream; final AtomicLong requested; final boolean nonScheduledRequests; Publisher<T> source; SubscribeOnSubscriber(Subscriber<? super T> actual, Scheduler.Worker worker, Publisher<T> source, boolean requestOn) { this.downstream = actual; this.worker = worker; this.source = source; this.upstream = new AtomicReference<Subscription>(); this.requested = new AtomicLong(); this.nonScheduledRequests = !requestOn; } @Override public void run() { lazySet(Thread.currentThread()); Publisher<T> src = source; source = null; src.subscribe(this); } @Override public void onSubscribe(Subscription s) { if (SubscriptionHelper.setOnce(this.upstream, s)) { long r = requested.getAndSet(0L); if (r != 0L) { requestUpstream(r, s); } } } @Override public void onNext(T t) { downstream.onNext(t); } @Override public void onError(Throwable t) { downstream.onError(t); worker.dispose(); } @Override public void onComplete() { downstream.onComplete(); worker.dispose(); } @Override public void request(final long n) { if (SubscriptionHelper.validate(n)) { Subscription s = this.upstream.get(); if (s != null) { requestUpstream(n, s); } else { BackpressureHelper.add(requested, n); s = this.upstream.get(); if (s != null) { long r = requested.getAndSet(0L); if (r != 0L) { requestUpstream(r, s); } } } } } void requestUpstream(final long n, final Subscription s) { if (nonScheduledRequests || Thread.currentThread() == get()) { s.request(n); } else { worker.schedule(new Request(s, n)); } } @Override public void cancel() { SubscriptionHelper.cancel(upstream); worker.dispose(); } static final class Request implements Runnable { final Subscription upstream; final long n; Request(Subscription s, long n) { this.upstream = s; this.n = n; } @Override public void run() { upstream.request(n); } } } } -
定义一个处理器,指定线程处理下游订阅者:当前处理器处理下游订阅者,指定线程处理指定方法-onNext、onComplete、onError;
public final class FlowableObserveOn<T> extends AbstractFlowableWithUpstream<T, T> { final Scheduler scheduler; final boolean delayError; final int prefetch; public FlowableObserveOn( Flowable<T> source, Scheduler scheduler, boolean delayError, int prefetch) { super(source); this.scheduler = scheduler; this.delayError = delayError; this.prefetch = prefetch; } @Override public void subscribeActual(Subscriber<? super T> s) { Worker worker = scheduler.createWorker(); //因为下游订阅者不是全部方法都在指定线程上处理,所以把工作线程worker作为参数传递给当前对象,目的是执行我们需要在指定线程上处理的方法 //当前订阅者对象作为下游对象,传递给上一个处理器,目的是上一个处理器的订阅者执行onNext接受(onComplete,onError)数据方法时传递到当前订阅者对象中 source.subscribe(new ObserveOnSubscriber<T>(s, worker, delayError, prefetch)); } ... }
扩展
操作符-数据流
上图所示Rxjava2支持的所有操作符。我们这里仅仅对map(最简单的一个)进行监督解析,情看FlowableMap类,核心方法如下:
解决背压问题
1.什么是背压
背压是一种现象,简单来说就是在异步操作中,上游发送数据速度快于下游处理数据的速度,下游来不及处理,Buffer 溢出,导致事件阻塞,从而引起的各种问题,比如事件丢失,OOM等。
在rxjava1中并不支持背压,当出现事件阻塞时候,会直接抛出 MissingBackpressureException 异常,但是在rxjava2中,提供了 Flowable 来创建被观察者,通过Flowable 来处理背压问题,我们可以简单通过demo分析。
A:我们上游模拟循环发送数据。
B:线程切换,异步操作。
C:下游每隔一秒获取数据。
我们Observable 创建,来模拟了背压这个现象,我们在上游模拟无限循环的发送数据,下游每次都休眠一秒再获取数据,这样肯定会造成我们前面提的问题,就是上游发送太他丫的快了,下游根本处理不过来,我们先看结果。
看日志,打印结果停留在了13就没有继续打印了?同时可以看到程序已经崩了,是因为在rxjava2中,Observable并不支持背压操作,遇到背压问题,它并不会报错,也不会抛MissingBackpressureException 异常,但是内存会一直飙高,最后导致内存不足程序直接挂掉。
2.如何解决背压问题
我们设置两个参数,一个参数用来确定发射器发送数据的最大个数,一个参数用来确定订阅者一次性接受数据最大个数,并且如果订阅者没有设置一次性接受数据最大个数,那么当前发射器数据始终存在于缓存中。
-
通过
Subscription对象的request方法设置被订阅者的最大接受数据(默认设置128)和订阅者一次性接受最大数据(必须用户手动设置); -
FlowableObserveOn类中有一个runAsync方法,该方法有一个轮询,直到订阅者设置了一次性最大接受数据才会开始接受数据
五种观察者模式
参考
总结
以上包括前面的文章,好坏参半,也表现了作者当前水平。Rxjava2目前来说解说完毕,后面可能还会对当前的知识重新理解。
每一次认真阅读源码都有不一样的收获。
当前源码标签使用AAC-Rxjava2篇