RxJava源码分析

RxJava简介

概念

“RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-based programs by using observable sequences.”

—— RxJava Repo

        RxJava是Java VM上一个灵活的、使用可观测序列来组成的一个异步的、基于事件的库。

作用 - 异步

        核心的东西不外乎两个, Observables(被观察者) 和 Subscribers(观察者)。Observables可以发出一系列的 事件,这里的事件可以是任何东西,例如网络请求、复杂计算、数据库操作、文件读取等等,事件执行结束后交给Subscribers的回调处理。

设计模式 - 观察者模式

        观察者模式是对象的行为模式,也叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。 例如用过EventBus同学就知道,EventBus属于Publish/Subscribe模式。

        什么是观察者模式?举个例子,Android中View的点击监听器的实现,View是被观察者,OnClickListener对象是观察者,Activity要如何知道View被点击了?那就是派一个OnClickListener对象,入驻View,与View达成一个订阅关系,一旦View被点击了,就通过OnClickListener对象的OnClick方法传达给Activity。采用观察者模式可以避免去轮询检查,节约有限的cpu资源。

结构 - 响应式编程

        什么是响应式编程?举个例子,a = b + c; 这句代码将b+c的值赋给a,而之后如果b和c的值改变了不会影响到a,然而,对于响应式编程,之后b和c的值的改变也动态影响着a,意味着a会随着b和c的变化而变化。

优势 - 逻辑简洁

        逻辑简洁并不意味着代码简洁,但是,由于链式结构,一条龙,你可以从头到尾,从上到下,很清楚的看到这个连式结构的执行顺序。对于开发人员来说,代码质量并不在于代码量,而在于逻辑清晰简洁,可维护性好,代码健壮!

初始化源码分析 

观察者 Observer

        只是一个接口,具体实现由用户决定

public interface Observer<@NonNull T> {

    void onSubscribe(@NonNull Disposable d); // 订阅后回调

    void onNext(@NonNull T t); // 接受下一个事件时回调

    void onError(@NonNull Throwable e); // 出现错误时回调(比如抛异常)

    void onComplete(); // 事件流完成后回调

}

被观察者 Observable

        会返回一个 ObservableCreate<T>,就是自定义Source

订阅过程分析

主流程分析

        使用一个简单的示例:create后直接subscribe

示例代码

// 起点
Observable.create(
    object : ObservableOnSubscribe<String> {
        override fun subscribe(emitter: ObservableEmitter<String>) {
            // emitter 就是自定义 Source
            // 最终让 ObservableCreate.source: ObservableOnSubscribe<T> 保存 【埋下伏笔】
            emitter.onNext("RxJava") // 开始拆洋葱模型【一级包裹】
        }
    }
)

    .subscribe(
        // 终点
        object : Observer<String> {
            override fun onSubscribe(d: Disposable) {
            }

            override fun onError(e: Throwable) {
            }

            override fun onComplete() {
            }

            override fun onNext(t: Boolean) {
                Log.d(TAG, "this is onNext()")
            }
        }
    )

流程分析

        在起点Obserable和终点Observer,都是面向接口编程(依赖倒置原则)。框架只实现思路(接口),具体代码(实现)由用户完成。

        e.onNext()就是拆包裹的开始,这就是为什么想要启动整个事件流必须要在Observable中写e.onNext()的原因。

        source是ObservableSource<T>类型,ObservableSource<T>实际上是个接口,内部只有一个subscribe,传递了终点Observer。

map变换流程分析

        使用一个简单的示例:create后连接一次map,之后直接subscribe

示例代码

// 起点
Observable.create(
    object : ObservableOnSubscribe<String> {
        override fun subscribe(emitter: ObservableEmitter<String>) {
            // emitter 就是自定义 Source
            // 最终让 ObservableCreate.source: ObservableOnSubscribe<T> 保存了 【埋下伏笔】
            emitter.onNext("RxJava") // 开始拆洋葱模型【一级包裹】
        }
    }
)

    // 需求一
    /**
     * map 变换
     */
    .map {
        // 框架不管细节,将细节交给用户(面向接口编程 / 依赖倒置原则)
        return@map 1
    }

    .subscribe(
        // 终点
        object : Observer<Boolean> {
            override fun onSubscribe(d: Disposable) {
                Log.d(TAG, "this is onSubscribe()")
            }

            override fun onError(e: Throwable) {
                Log.d(TAG, "this is onError()")
            }

            override fun onComplete() {
                Log.d(TAG, "this is onComplete()")
            }

            override fun onNext(t: Boolean) {
                Log.d(TAG, "this is onNext()")
            }
        }
    )

流程分析

        总体上,加入map操作符的流程和不加map操作符的流程大同小异,但是需要特别关注的是ObserverMap中的onNext方法。

        我们来看下源码:

// ObserverMap.java
final Function<? super T, ? extends U> mapper

@Override
public void onNext(T t) {
    if (done) {
        return;
    }

    if (sourceMode != NONE) {
        downstream.onNext(null);
        return;
    }

    U v;

    try {
        v = Objects.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
    } catch (Throwable ex) {
        fail(ex);
        return;
    }
    downstream.onNext(v);
}

// Function.java
public interface Function<@NonNull T, @NonNull R> {
    R apply(T t) throws Throwable;
}

        这里面的mapper实际上就是我们map操作符传进来的一个函数。而mapper.apply(t),本质是个接口,主要定义将T类型转为R类型,具体实现交给用户,又是面向接口编程。

结构

洋葱模型

        就是RxJava对Observable<T>的一层层封装(这里借用一下网图,犯懒了)

U型结构

        U型结构就是我们上面分析的两张订阅流程图中,红色箭头的流程

M型结构

    主要包含三次数据的封装和拆解:

  • 第一次,从Observable到Observer,将被观察者一层层包裹

  • 第二次,从subscribe开始到ObservableOnSubscribe,根据包裹的被观察者创建出包裹的观察者

  • 第三次,Observable的源头启动onNext()开始拆包裹,各个Observer观察到相应的Observable,并完成用户的操作,一直到最终的Observer被调用,完成用户实现的接口逻辑

线程切换

线程调度器

Schedulers.computation()

用于计算任务,如事件循环或和回调处理,不要用于IO操作(IO操作请使用Schedulers.io());默认线程数等于处理器的数量

Schedulers.from(executor)

使用指定的Executor作为调度器

Schedulers.immediate( )

在当前线程立即开始执行任务

Schedulers.io( )

用于IO密集型任务,如数据库读写,网络请求等

Schedulers.newThread( )

为每个任务创建一个新线程

Schedulers.trampoline( )

当其它排队的任务完成后,在当前线程排队开始执行

AndroidSchedulers.mainThread()

用于Android的UI更新操作,任务执行在主线程中,一帮设置为observeOn的调度器,用于下游接收到数据流后更新UI

subscribeOn()线程调度

        在scheduleDirect中会从线程池中拿线程,而SubscribeTask就是一个Runnable,会执行source.subscribe(),这就联系到上面的流程图了。

// ObservableSubscribeOn.java
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    final Worker w = createWorker();

    final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);

    DisposeTask task = new DisposeTask(decoratedRun, w);

    w.schedule(task, delay, unit);

    return task;
}

// IoSchedular.java
@NonNull
@Override
public Worker createWorker() {
    return new EventLoopWorker(pool.get());
}

observerOn()线程调度

    ObserveOnObserver有两点比较关键:

  • schedule()方法,最终调用到Observer.onNext(),可结合到上面的流程图

  • onNext()方法,最终调用ScheduleRunnable.setFuture(),使用线程池完成线程切换

// NewThreadWorker.java
@NonNull
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
    Runnable decoratedRun = RxJavaPlugins.onSchedule(run);

    ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);

    if (parent != null) {
        if (!parent.add(sr)) {
            return sr;
        }
    }

    Future<?> f;
    try {
        if (delayTime <= 0) {
            f = executor.submit((Callable<Object>)sr);
        } 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;
}

public void setFuture(Future<?> f) {
    for (;;) {
        Object o = get(FUTURE_INDEX);
        if (o == DONE) {
            return;
        }
        if (o == SYNC_DISPOSED) {
            f.cancel(false);
            return;
        }
        if (o == ASYNC_DISPOSED) {
            f.cancel(true);
            return;
        }
        if (compareAndSet(FUTURE_INDEX, o, f)) {
            return;
        }
    }
}

相关参考

RxJava详解,由浅入深

RxJava(二)——原理与源码

Carson带你学Android:图文解析RxJava背压策略

  • 40
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值