1、响应式编程
响应式编程特点
- 事件从起点到终点进行流转,中途不发生中断,但可以对事件进行拦截,并对事件的数据进行转换处理
- RxJava的使用主要通过各个操作符进行处理
- 在事件流程过程中,需要对数据进行处理,可通过操作符进行转换
- RxJava采用链式调用,与传统编码方式相比,一行代码可实现复杂功能,而且可优雅处理多层回调的问题
- 业务开发过程中,耗时操作在子线程处理,数据结果在主线程展示,RxJava通过操作符完美实现线程切换操作
2、RxJava的使用
2.1、添加依赖
- rxjava是基本库,rxandroid是扩展在安卓领域使用的库,封装了Android消息机制功能
arduino
implementation 'io.reactivex.rxjava3:rxjava:3.1.5'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
2.2、RxJava的基本使用
- create 方法创建被观察者对象(Observable),真实实现类是ObservableCreate,create方法接收参数ObservableOnSubscribe
- 创建观察者Observer对象
- 订阅方法subscribe,将观察者与被观察者联系起来,当在ObservableOnSubscribe的subscribe中调用发射emitter的onNext方法对象数据,最终该数据会流转到观察者的onNext方法中进行接收
问题:
-
为什么在ObservableOnSubscribe的subscribe方法中,调用对象emitter的onNext方法发射数据,最终该数据会流转到观察者的onNext方法?
kotlinObservable.create(object : ObservableOnSubscribe<String> { override fun subscribe(emitter: ObservableEmitter<String>) { // 发射 emitter.onNext("11") emitter.onNext("12") emitter.onNext("13") emitter.onComplete() } }).subscribe(object : Observer<String> { override fun onSubscribe(d: Disposable) { println("RxJava onSubscribe") } override fun onError(e: Throwable) { println("RxJava onError:$e") } override fun onComplete() { println("RxJava onComplete") } override fun onNext(t: String) { println("RxJava onNext:$t") } })
日志信息:
I/System.out:
I/System.out: RxJava onNext:11
I/System.out: RxJava onNext:12
I/System.out: RxJava onNext:13
I/System.out: RxJava onComplete
create方法
- io.reactivex.rxjava3.core.Observable#create
- create方法中会传入入参ObservableOnSubscribe对象,可理解为自定义被观察者source,接着创建ObservableCreate实例对象,并将source作为参数传入
- 接着调用RxJavaPlugins.onAssembly方法,该方法中会判断静态属性onObservableAssembly是否为空,默认为空,所以create方法最终返回的是ObservableCreate对象
- onObservableAssembly属性可通过RxJavaPlugins.setOnObservableAssembly方法,设置自定义的被观察则对象
typescript
public static <@NonNull T> Observable<T> create(@NonNull ObservableOnSubscribe<T> source) {
Objects.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<>(source));
}
io.reactivex.rxjava3.plugins.RxJavaPlugins#onAssembly(io.reactivex.rxjava3.core.Observable<T>)
public static <@NonNull T> Observable<T> onAssembly(@NonNull Observable<T> source) {
Function<? super Observable, ? extends Observable> f = onObservableAssembly; // f默认为空,直接返回source
if (f != null) {
return apply(f, source);
}
return source;
}
static volatile Function<? super Observable, ? extends Observable> onObservableAssembly;
public static void setOnObservableAssembly(@Nullable Function<? super Observable, ? extends Observable> onObservableAssembly) {
if (lockdown) {
throw new IllegalStateException("Plugins can't be changed anymore");
}
RxJavaPlugins.onObservableAssembly = onObservableAssembly;
}
创建Observer对象
- 这块没啥好说的,实现Observe接口的匿名内部类
订阅方法subscribe
- io.reactivex.rxjava3.core.Observable#subscribe(io.reactivex.rxjava3.core.Observer<? super T>)
- 因为create方法最终返回的是ObservableCreate对象,所以订阅方法调用的实现类也是它,最终会调用ObservableCreate的subscribeActual方法,并将观察者传入其中
less
public final void subscribe(@NonNull Observer<? super T> observer) {
Objects.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
subscribeActual(observer);
} catch (NullPointerException e) { // NOPMD
...
}
核心方法:实现订阅功能 ObservableCreate.subscribeActual
- io.reactivex.rxjava3.internal.operators.observable.ObservableCreate#subscribeActual
- ObservableCreate的属性source,是调用Observable.create方法传入的ObservableOnSubscribe对象
- 创建发射类CreateEmitter,将观察者对象observer作为参数传入
- 接着先调用观察则和的onSubscribe方法
- 最后调用ObservableOnSubscribe的subscribe方法,并将发射类CreateEmitter作为参数传入
- 这样在ObservableOnSubscribe的subscribe实现方法中,可拿到发射类CreateEmitter调用onNext方法发射数据
- 而在CreateEmitter中,onNext方法调用的是观察者的onNext方法,这样实现了内部的数据流转
java
public final class ObservableCreate<T> extends Observable<T> {
final ObservableOnSubscribe<T> source;
public ObservableCreate(ObservableOnSubscribe<T> source) {
this.source = source;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
// 创建发射类CreateEmitter,将观察者对象observer作为参数传入
CreateEmitter<T> parent = new CreateEmitter<>(observer);
// 先调用观察则和的onSubscribe方法
observer.onSubscribe(parent);
try {
// 最后调用ObservableOnSubscribe的subscribe方法,
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
static final class CreateEmitter<T>
extends AtomicReference<Disposable>
implements ObservableEmitter<T>, Disposable {
private static final long serialVersionUID = -3434801548987643227L;
final Observer<? super T> observer;
CreateEmitter(Observer<? super T> observer) {
this.observer = observer;
}
// 调用发射类CreateEmitter的onNext方法发射数据,最终会调用观察者observer的onNext方法
@Override
public void onNext(T t) {
if (t == null) {
onError(ExceptionHelper.createNullPointerException("onNext called with a null value."));
return;
}
if (!isDisposed()) {
observer.onNext(t);
}
}
@Override
public void onError(Throwable t) {
if (!tryOnError(t)) {
RxJavaPlugins.onError(t);
}
}
@Override
public boolean tryOnError(Throwable t) {
if (t == null) {
t = ExceptionHelper.createNullPointerException("onError called with a null Throwable.");
}
if (!isDisposed()) {
try {
observer.onError(t);
} finally {
dispose();
}
return true;
}
return false;
}
@Override
public void onComplete() {
if (!isDisposed()) {
try {
observer.onComplete();
} finally {
dispose();
}
}
}
...
}
}
画图理解
- 上述RxJava的使用可以分为三个步骤:创建被观察者,创建观察者和调用订阅方法subscribe
- 而数据最终从上到下进行流转,内部实现的核心是在被观察者的具体实现类的subscribeActual方法中进行处理
- RxJava的源码理解之所以绕,主要在他的参与类非常多,只有理清楚各个类组成和他们的相互调用关系,才能更好地理解RxJava框架的设计原理
RxJava基本使用时序图
对应流程图
3、map操作符解析
- 在业务开发过程中,中途对数据进行处理后再使用这种场景非常常见,在RxJava框架中可通过map操作符进行处理
- 例子
kotlin
Observable.create(object : ObservableOnSubscribe<Int> {
override fun subscribe(emitter: ObservableEmitter<Int>) { // 发射
emitter.onNext(21)
emitter.onNext(22)
emitter.onNext(23)
emitter.onComplete()
}
}).map { // int类型数据增加2后,转换成String类型数据
val t = it + 2
"result-$t"
}.subscribe(object : Observer<String> {
override fun onSubscribe(d: Disposable) {
println("RxJava onSubscribe")
}
override fun onError(e: Throwable) {
println("RxJava onError:$e")
}
override fun onComplete() {
println("RxJava onComplete")
}
override fun onNext(t: String) {
println("RxJava onNext:$t")
}
})
map方法
- io.reactivex.rxjava3.core.Observable#map
- 解析,在map方法之前调用了create方法返回的结果是ObservableCreate,所以调用map的实现类是ObservableCreate,
- 创建ObservableMap对象,this参数就是上面的ObservableCreate对象实例,还有Function数据转换实现类
typescript
RxJavaPlugins.onAssembly之前分析过,是作为自定义拦截处理,默认为空
public final <@NonNull R> Observable<R> map(@NonNull Function<? super T, ? extends R> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap<>(this, mapper));
}
ObservableMap
- io.reactivex.rxjava3.internal.operators.observable.ObservableMap
- ObservableMap的构造函数持有的source属性是ObservableCreate对象实例
ObservableMap.subscribeActual
- subscribeActual方法由ObservableMap的订阅方法触发调用,首先会创建MapObserver,将将观察者对象传入,该观察者就是事件的终点观察者
- 接着调用 source.subscribe方法,因为该source是ObservableCreate对象实例,调用该方法后接着调用ObservableCreate.subscribeActuat方法,且入参持有的观察者是MapObserver对象实例
- 接下来调用逻辑就是ObservableCreate.subscribeActuat方法,不同点在于ObservableMap构造函数持有source是ObservableCreate对象实例;而ObservableCreate构造函数持有source是ObservableOnSubscribe对象实例。
得出规律:
- RxJava的每个操作符方法xxx调用后都会创建一个对应的被观察者(ObservableXxx),除了第一个操作符(create,just等)外,中间的操作符在创建对应观察者ObservableXxx时,都会持有上一个操作符创建的被观察者ObservableXxx(before)
- 当调用订阅方法subscribe传入最终的观察者时,会调用subscribeActual方法,该方法中会创建自己内部的一个观察者对象(XxxObserver),并调用上一个操作符对应的被观察者的订阅方法,订阅方法都需要传入观察者,此时传入的当前操作符对应被观察者内部创建的观察者(XxxObserver)
- 按照这个逻辑一直往上调用订阅方法,在当前操作符中,会调用上一个操作符对应被观察者的订阅方法,并传入内部创建的观察者对象(该观察者持有下一个观察者的引用),这样在数据下发的时候,会通过观察者的引用链,不断将数据下发流转
数据流转:
- ObservableMap中会创建内部的观察者MapObserver,subscribeActual方法中会调用ObservableCreate的订阅方法subscribe,并传入观察者MapObserver对象,
- 这样在ObservableCreate的subscribeActual方法中,会创建CreateEmitter对象,并持有MapObserver观察者对象
- 当调用CreateEmitter对象的onNext方法下发数据时,会调用MapObserver.onNext方法,在MapObserver的onNext方法中,会调用mapper.apply(t)方法对数据进行转换,并最终调用重点观察者Observer的onNext方法
scala
public final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
final Function<? super T, ? extends U> function;
public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
super(source);
this.function = function;
}
@Override
public void subscribeActual(Observer<? super U> t) {
source.subscribe(new MapObserver<T, U>(t, function));
}
static final class MapObserver<T, U> extends BasicFuseableObserver<T, U> {
final Function<? super T, ? extends U> mapper;
MapObserver(Observer<? super U> actual, Function<? super T, ? extends U> mapper) {
super(actual);
this.mapper = mapper;
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
downstream.onNext(null);
return;
}
U v;
try { // 数据转换处理后,继续往下传递 -》onNext
v = Objects.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
} catch (Throwable ex) {
fail(ex);
return;
}
downstream.onNext(v);
}
...
}
}
流程图
4、线程切换
- RxJava中有两个线程切换操作符,subscribeOn和observeOn
- 其中subscribeOn是给上面的操作部分切换线程操作
- observeOn是给下面操作部分切换线程
kotlin
Observable.create(object : ObservableOnSubscribe<Int> {
override fun subscribe(emitter: ObservableEmitter<Int>) { // 发射
emitter.onNext(31)
emitter.onNext(32)
emitter.onNext(33)
}
}).subscribeOn(Schedulers.io()) // 给上面切换到子线程
.observeOn(AndroidSchedulers.mainThread()) // 给下面切换到主线程
.subscribe(object : Observer<Int> {
override fun onSubscribe(d: Disposable) {
println("onSubscribe")
}
override fun onError(e: Throwable) {
println("onError:$e")
}
override fun onComplete() {
println("onComplete")
}
override fun onNext(t: Int) {
println("onNext:$t")
}
})
4.1、subscribeOn
Schedulers.io()
- io.reactivex.rxjava3.core.Scheduler
- Schedulers.io()方法最终会返回IoScheduler对象,该对象内部封装了线程池进行线程切换操作
- Schedulers其他方法调用会获取其他的Scheduler对象,不同的是内部使用了不同的线程池
arduino
public final class Schedulers {
...
@NonNull
static final Scheduler IO;
static final class IoHolder {
static final Scheduler DEFAULT = new IoScheduler();
}
static final class IOTask implements Supplier<Scheduler> {
@Override
public Scheduler get() {
return IoHolder.DEFAULT;
}
}
static {
SINGLE = RxJavaPlugins.initSingleScheduler(new SingleTask());
COMPUTATION = RxJavaPlugins.initComputationScheduler(new ComputationTask());
IO = RxJavaPlugins.initIoScheduler(new IOTask());
TRAMPOLINE = TrampolineScheduler.instance();
NEW_THREAD = RxJavaPlugins.initNewThreadScheduler(new NewThreadTask());
}
}
subscribeOn
- io.reactivex.rxjava3.core.Observable#subscribeOn
- 创建ObservableSubscribeOn被观察者对象
less
public final Observable<T> subscribeOn(@NonNull Scheduler scheduler) {
Objects.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<>(this, scheduler));
}
ObservableSubscribeOn
- io.reactivex.rxjava3.internal.operators.observable.ObservableSubscribeOn#ObservableSubscribeOn
- 当调用ObservableSubscribeOn.subscribeActual方法时,不是直接调用上一层操作符对应的被观察者对象source的订阅方法
- 而是会创建内部类SubscribeTask(实现了Runnable接口),并交给IoScheduler对象调用scheduleDirect方法,该方法会调用内部的线程池进行执行
- 这样前面所有的操作符执行的代码都在线程池中
java
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
super(source);
this.scheduler = scheduler;
}
@Override
public void subscribeActual(final Observer<? super T> observer) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<>(observer);
observer.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(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);
}
}
}
EventLoopWorker.schedule
- IoScheduler的scheduleDirect最终会调用EventLoopWorker的schedule
- io.reactivex.rxjava3.internal.schedulers.IoScheduler.EventLoopWorker#schedule
- 并最终交给内部线程池进行执行
- io.reactivex.rxjava3.internal.schedulers.NewThreadWorker#scheduleActual
less
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
// 对run任务进行封装
ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);
...
Future<?> f;
try {
if (delayTime <= 0) {
f = executor.submit((Callable<Object>)sr); // 调用线程池的submit方法,最终会在子线程中调用SubscribeTask 的run方法
} else {
f = executor.schedule((Callable<Object>)sr, delayTime, unit);
}
sr.setFuture(f);
} catch (RejectedExecutionException ex) {
if (parent != null) {
parent.remove(sr);
}
RxJavaPlugins.onError(ex);
}
return sr;
}
流程图
4.2、observeOn操作符
- AndroidSchedulers.mainThread()
- io.reactivex.rxjava3.android.schedulers.AndroidSchedulers#mainThread
- AndroidSchedulerss是RxAndroid库中的类,调用mainThread方法,会创建一个在主线程中执行任务的Scheduler对象
arduino
public final class AndroidSchedulers {
private static final class MainHolder {
static final Scheduler DEFAULT = internalFrom(Looper.getMainLooper(), true);
}
observeOn
- observeOn方法会创建ObservableObserveOn被观察者对象
- io.reactivex.rxjava3.core.Observable#observeOn(io.reactivex.rxjava3.core.Scheduler, boolean, int)
ObservableObserveOn.subscribeActual 订阅方法
- io.reactivex.rxjava3.internal.operators.observable.ObservableObserveOn#subscribeActual
- subscribeActual方法中会判断当前线程,最终在调用内部观察着的所有方法时,最终也是调用Scheduler的schedule(java.lang.Runnable)方法,最后通过Handler发送callback消息,切换到主线程执行
java
public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
final boolean delayError;
final int bufferSize;
public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
super(source);
this.scheduler = scheduler;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<>(observer, w, delayError, bufferSize));
}
}