RxJava 源码简单分析

再看 RxJava 之前,我们需要先了解一下在 RxJava 中的角色

ObservableSource 被观察者

Observer 观察者

Emitter 发射器

下面我们就从一个最简单的例子开始解读RxJava 的工作流程

kotlin 复制代码
var obs= Observable.create(object :ObservableOnSubscribe<String> {
    override fun subscribe(e: ObservableEmitter<String>?) {
        e?.onNext("1")
    }
})

obs.subscribe { 
    
}

为了让所有人都能看明白代码的加载顺序与执行顺序,这里没有采用链式调用的方法,而是创建变量来操作的,

我们先来 Observable.create 都干了什么

csharp 复制代码
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
    ObjectHelper.requireNonNull(source, "source is null");
    return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}

这里的代码异常的简单, 先来说一下 RxJavaPlugins.onAssembly 干了点啥,

typescript 复制代码
public static <T> Observable<T> onAssembly(Observable<T> source) {
    Function<Observable, Observable> f = onObservableAssembly;
    if (f != null) {
        return apply(f, source);
    }
    return source;
}

static <T, R> R apply(Function<T, R> f, T t) {
    try {
        return f.apply(t);
    } catch (Throwable ex) {
        throw ExceptionHelper.wrapOrThrow(ex);
    }
}

public static void setOnObservableAssembly(Function<Observable, Observable> onObservableAssembly) {
    if (lockdown) {
        throw new IllegalStateException("Plugins can't be changed anymore");
    }
    RxJavaPlugins.onObservableAssembly = onObservableAssembly;
}

onObservableAssembly 这个变量是RxJava 全局的静态变量,他能让我们看到每一次转换过程中都经历了什么,相当于一个后门,不过没见过哪里用到了这个,只能看修改会出现问题,并且从这里获取的信息比较有限,但是他确实是一个我们用的后门,

如果没有设置 RxJavaPlugins.onAssembly ,那么 只需要关心 new ObservableCreate(source)这段代码了

scala 复制代码
public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }
}

这段代码就是将我们 create 方法创建的 这个 ObservableOnSubscribe 持有一下,

kotlin 复制代码
 object :ObservableOnSubscribe<String> {
    override fun subscribe(e: ObservableEmitter<String>?) {
        e?.onNext("1")
    }
}

我们继续来分析 obs.subscribe { } 这段代码都干了什么,这个方法最终会流向 RxJava 中的 如下方法

java 复制代码
@SchedulerSupport(SchedulerSupport.NONE)
@Override
public final void subscribe(Observer<? super T> observer) {
    ObjectHelper.requireNonNull(observer, "observer is null");
    try {
        observer = RxJavaPlugins.onSubscribe(this, observer);

        ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");

        subscribeActual(observer);
    } catch (NullPointerException e) { // NOPMD
        throw e;
    } catch (Throwable e) {
        Exceptions.throwIfFatal(e);
        // can't call onError because no way to know if a Disposable has been set or not
        // can't call onSubscribe because the call might have set a Subscription already
        RxJavaPlugins.onError(e);

        NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
        npe.initCause(e);
        throw npe;
    }
}

observer = RxJavaPlugins.onSubscribe(this, observer); 这个方法同样是后门方法,这里就不分析了,然后就调用了 subscribeActual(observer); 这个方法 , 首先要清楚是谁调用的subscribe 方法,没错就是 ObservableCreate 这个类, 我们去看一下 ObservableCreate 他的 subscribeActual(observer) 方法

typescript 复制代码
@Override
protected void subscribeActual(Observer<? super T> observer) {
    CreateEmitter<T> parent = new CreateEmitter<T>(observer);
    observer.onSubscribe(parent);

    try {
        source.subscribe(parent);
    } catch (Throwable ex) {
        Exceptions.throwIfFatal(ex);
        parent.onError(ex);
    }
}

首先是先组装了一下 CreateEmitter 用来发射用的 ,然后马上就调用了 observer.onSubscribe 这个回调,所以每次必然都是 onSubscribe 这个方法第一个回调 , 然后就调到了我们在create 的时候传入的回调,而我们在create 的时候调用的是 Emitter 的noNext 方法 ,那么我们先来看看 CreateEmitter 的next 干了啥

typescript 复制代码
CreateEmitter(Observer<? super T> observer) {
    this.observer = observer;
}

@Override
public void onNext(T t) {
    if (t == null) {
        onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
        return;
    }
    if (!isDisposed()) {
        observer.onNext(t);
    }
}

可以看到 onNext 直接调用的 subscribe 传入的 Observe 的 onNext 回调,整个流程就分析完成了,但是只看一个create 的操作符是感受不到Rxjava 的伟大之处的,但是又为什么将只有一个create 就 调用 subscribe 的拿出来说呢,主要目的是为了先让大家对于他的流程有个大概的理解,加入更多操作符后理解起来更加的轻松

在加入更多的操作符前,只通过一个create我们能看到什么,

RxJava 是一个冷流,只有在 subscribe 调用才才会触发上游开始发送事件,再仔细体会一下是不是这个道理

crate map subscribe

先上例子

kotlin 复制代码
Observable.create(object : ObservableOnSubscribe<Int> {
    override fun subscribe(e: ObservableEmitter<Int>) {
        e.onNext(1)
    }
}).map {
    return@map "变换后的$it"
}.subscribe {
    Log.i("tian.shm", "$it")
}

这里还是先创建 ObservableCreate

scala 复制代码
public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }
}

然后调用 ObservableCreate.map 变化

less 复制代码
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
    ObjectHelper.requireNonNull(mapper, "mapper is null");
    return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}

仔细看这里使用的 ObservableCreate 的 又创建了一个 ObservableMap,注意在创建ObservableMap的时候使用的this,也就是在create操作符创建的 ObservableCreate, 我们再先来看看

typescript 复制代码
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));
    }
}

Map 操作符的创建也是平平无奇

但是这里需要画一个图来标识我们创建的关系

在我们使用了create 与 map 操作符后,形成的包裹关系就变成了这个样子,代码在没有调用到 subscribe 之前是一层一层包裹起来的,

当我们调用 subscribe 方法后就相当于我们调用了 ObservableMap 的 subscribeActual方法,我们先来看一下代码,

typescript 复制代码
@Override
public void subscribeActual(Observer<? super U> t) {
    source.subscribe(new MapObserver<T, U>(t, function));
}

可以看到 这里有调用到了 ObservableCreate 的 subscribeActual 的方法里面,使用Map 的监听将 subscribe 的监听包裹一下,那么上层的 ObservableCreate 他的观察者就是 MapObserve,这样 MapObserve 就可以转换数据了,

整个过程使用图片就变成了下面这个样子

看了这张图片后整个流程瞬间就清晰多了,这个里面有点绕,大家可以配合这源码再自己分析一下这个流程

crate map1 subscribeOn map2 observeOn map3 subscribe

其实这个流程主要是想介绍一下 subscribeOn 与 observeOn ,以及为什么他们能做到线程调度,并且说明一下他们的都能调度那个阶段的代码

了解了上面的包裹的这个过程,这里我们就能直接看一下

scala 复制代码
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> s) {
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);

        s.onSubscribe(parent);

        parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
            @Override
            public void run() {
                source.subscribe(parent);
            }
        }));
    }
}

从代码的逻辑可以看出来,在使用 ObservableSubscribeOn 包裹后, 使用 subscribe 订阅后,执行到 ObservableSubscribeOn 后,会使用 scheduler 将包裹内的继续向上查找的线程改变了,而且也将发射的线程也改变了,看到网上很多人都说 subscribeOn 只能改变上层的线程,其实这里是不对的,如果没有调度指令的话,除了在 subscribe 过程中 包裹 ObservableSubscribeOn 的线程没有改变,所有的线程都被改变了,为了证明这个结论创建了下面的例子

kotlin 复制代码
Observable.create(ObservableOnSubscribe<String> {
    Log.i("tian.shm","create  Thread Name:${Thread.currentThread().name}")
    it.onNext("1")
}) .map {
    Log.i("tian.shm","map1  Thread Name:${Thread.currentThread().name}")
    return@map it
}.subscribeOn(Schedulers.io())
    .map {
        Log.i("tian.shm","map2  Thread Name:${Thread.currentThread().name}")
        return@map it
    }
    .observeOn(AndroidSchedulers.mainThread())
    .map {
        Log.i("tian.shm","map3  Thread Name:${Thread.currentThread().name}")
        return@map it
    }
    .subscribe {
        Log.i("tian.shm","Thread Name:${Thread.currentThread().name}")
    }

结果如下

ruby 复制代码
: create  Thread Name:RxCachedThreadScheduler-1
: map1  Thread Name:RxCachedThreadScheduler-1
: map2  Thread Name:RxCachedThreadScheduler-1
: map3  Thread Name:main
: Thread Name:main

看完了 subscribeOn 是在向上查找过程中改变了线程,那么 observeOn 这个就非常容易想到他是在哪里改变的线程

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<T>(observer, w, delayError, bufferSize));
        }
    }
}

在 ObservableObserveOn 这个类中,他将 Scheduler.Worker 这个worker 传入了 ObserveOnObserver 中了,没错,他就是在 ObserveOnObserver 中改变结果的监听的

scss 复制代码
@Override
public void onNext(T t) {
    if (done) {
        return;
    }

    if (sourceMode != QueueDisposable.ASYNC) {
        queue.offer(t);
    }
    schedule();
}

void schedule() {
    if (getAndIncrement() == 0) {
        worker.schedule(this);
    }
}

可以看到确实是这个样子的, observeOn改变的是发射数据后,执行Observe过程中的线程, 到了这里整个RxJava 的简单分析就完成了

相关推荐
liufeismart202411 天前
Android 第三方框架:RxJava:源码分析:责任链模式
责任链模式·rxjava
lhy__14 天前
给初学者的RxJava2.0教程(一)
android·rxjava
liufeismart202418 天前
Android 第三方框架:RxJava:源码分析:观察者模式
android·rxjava
忆~遂愿21 天前
探索云开发Copilot,AI如何重塑开发流程?
人工智能·python·深度学习·神经网络·机器学习·copilot·rxjava
xingsfdz25 天前
reactivex.Observable 超时问题
rxjava·observable·数据流
帅次1 个月前
Android CoordinatorLayout:打造高效交互界面的利器
android·gradle·android studio·rxjava·android jetpack·androidx·appcompat
命运之手2 个月前
【Android】Analysis of Empty Observable in RxJava
android·rxjava·empty·observable
追梦的鱼儿4 个月前
okhttp,retrofit,rxjava 是如何配合工作的 作用分别是什么
okhttp·rxjava·retrofit
故事不长丨4 个月前
RxJava在Android中的应用
android·java·echarts·rxjava
九霄云客5 个月前
SuccBI+低代码文档中心 — 低代码应用(SuperPage)(上)(重点)
android·低代码·rxjava