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 的简单分析就完成了

相关推荐
松仔log10 天前
JetPack——Paging
android·rxjava
吴声子夜歌11 天前
RxJava——Subscriber
android·echarts·rxjava
吴声子夜歌11 天前
RxJava——Flowable与背压
android·java·rxjava
吴声子夜歌13 天前
RxJava——Hot Observable和Cold Observable
android·rxjava
吴声子夜歌15 天前
RxJava——调度器Scheduler
android·echarts·rxjava
吴声子夜歌15 天前
RxJava——并行编程
android·echarts·rxjava
吴声子夜歌18 天前
RxJava——FlowableProcessor详解
android·echarts·rxjava
Zoho低代码开发工具18 天前
APP开发工具哪个好?国内外热门的开发工具推荐
android·rxjava
吴声子夜歌18 天前
RxJava——Subject详解
android·echarts·rxjava
Zoho低代码开发工具18 天前
2026年,用低代码开发系统的公司都有哪些特点?
android·rxjava