RxJava2源码分析——基本元素(一)

文章主要记录自己学习源码的过程,不会对如如何使用做过多介绍。自己是初学者,只是为了学习记录。
基于:
implementation ‘io.reactivex.rxjava2:rxandroid:2.1.0’
implementation ‘io.reactivex.rxjava2:rxjava:2.2.3’

介绍:

a library for composing asynchronous and event-based programs using observable sequences for the Java VM
一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库。

Rxjava是一种面向数据流和变化传播的开源库。所谓的数据流是指:只能以事先规定好的顺序被读取一次的数据的一个序列。变化传播可以理解为观察者模式,当被观察者发生了变化就需要去通知观察者,这就是变化传播。
举一个简单的栗子。
在这里插入图片描述
上图履带上的一系列产品就可以看作是数据流,他只能以事先规定好的顺序被处理,当我们给他加上盖子后其实就是对他做了变化,这种变化会被传播到下一个环节,这样看是不是很容易就理解了什么是数据流,什么是变化传播?

首先分析无背压版的流程
从最简单的代码开始分析:

 Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(5);
                emitter.onNext(4);
                emitter.onComplete();
            }
        }).subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Integer integer) {
              Log.d(TAG,"onNext:"+integer);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
                Log.d(TAG,"onComplete:");
            }
        });

打印结果:

D/MainActivity: onNext:5
D/MainActivity: onNext:4
D/MainActivity: onComplete:

从这个简单的代码可以看出有哪些基本元素

  1. Observable 被观察者,不支持背压。
  2. Observer 观察者,用于接收数据。作为Observable的subscribe方法的参数。
  3. Disposable 用于取消订阅和获取当前的订阅状态。和RxJava1的Subscription
    作用相当。
  4. Emitter 用于发射数据,本质上是对Observer的封装。
  5. ObservableOnSubscribe 当订阅时触发此接口。

在分析执行流程前先热个身

public interface Observer<T> {
    void onSubscribe(@NonNull Disposable d);
    void onNext(@NonNull T t);
    void onError(@NonNull Throwable e);
    void onComplete();
}

观察者是一个接口,它提供了4个方法,当上游(被观察者)调用onNext,onComplete,发生错误,都会将结果回调到观察者对应的方法中。

public interface ObservableOnSubscribe<T> {
    void subscribe(@NonNull ObservableEmitter<T> emitter) throws Exception;
}

ObservableOnSubscribe也是一个接口,它里面只有一个subscribe方法,该方法接受ObservableEmitter类型参数。
执行流程源码分析:
上面的栗子中,首先调用Observable.create()方法并给它传入了一个ObservableOnSubscribe类型匿名对象,看看Observable.create()方法干了什么。

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

首先创建了ObservableCreate对象并把ObservableOnSubscribe匿名对象作为它的参数传进去。
RxJavaPlugins.onAssembly()这个方法又干了什么?

public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
        Function<? super Observable, ? extends Observable> f = onObservableAssembly;
        if (f != null) {
            return apply(f, source);
        }
        return source;
    }

onObservableAssembly默认为空,因此这个方法直接将创建的ObservableCreate对象返回了。

接着又调用了subscribe()并将观察者传进去,其实是调用ObservableCreate对象的subscribe()方法,点进去ObservableCreate对象的subscribe()方法看一下会发现subscribe()方法是ObservableCreate父类Observable的方法。
Observable#

 public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
        	//这里返回的就是我们传进来的观察者对象observer
            observer = RxJavaPlugins.onSubscribe(this, observer);
            //...
            subscribeActual(observer);
            //...
        } 
    }

    protected abstract void subscribeActual(Observer<? super T> observer);

接着直接调用了subscribeActual(observer)方法,该方法在父类Observable是一个抽象方法,具体由子类实现,因此它最终会走到ObservableCreate的subscribeActual()方法
ObservableCreate#subscribeActual(Observer<? super T> observer)

 @Override
    protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);//1
        observer.onSubscribe(parent);//2
        try {
            source.subscribe(parent);//3
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);//4  出现异常就调用观察者的onError方法
        }
    }

在注释1会创建CreateEmitter对象对观察者进行包装,注释2直接调用观察者的onSubscribe方法,看到没?观察者对象的onSubscribe方法就是这里被调用的。接下来注释3调用source.subscribe(parent)方法,这个source就是我们Observable.create()方法传入的ObservableOnSubscribe对象,回顾一下。

 Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(5);
                emitter.onNext(4);
                emitter.onComplete();
            }
        })

这样就直接把我们的观察者的包装对象CreateEmitter传进来了,在里面调用它的onNext(),onComplete最终都会直接调用观察者的onNext,onComplete方法。

static final class CreateEmitter<T>  extends AtomicReference<Disposable>
    implements ObservableEmitter<T>, Disposable {
    
        final Observer<? super T> observer;

        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);
            }
        }
        //....省略部分代码。
        @Override
        public void onComplete() {
            if (!isDisposed()) {
                try {
                    observer.onComplete();
                } finally {
                    dispose();
                }
            }
        }

梳理:
1、首先调用Observable的create方法,并且传入一个ObservableOnSubscribe对象作为source。create返回一个ObservableCreate对象,该对象持有source。
2、调用ObservableCreate对象的subscribe方法,并将观察者传入,subscribe方法又会调用subscribeActual(observer)方法。
3、然后直接调用source的subscribe方法并将观察者包装对象传进去。
4、在source#subscribe方法中调用的onNext,onComplete方法,本质上就是直接调用观察者的方法。

分析完无背压的简单执行过程,再来看看有背压的。

有背压版的执行流程
还是从最简单的代码开始。

  Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                emitter.onNext("1");
                emitter.onNext("2");
                emitter.onComplete();
            }
        }, BackpressureStrategy.DROP)
                .subscribe(new Subscriber<String>() {
            @Override
            public void onSubscribe(Subscription s) {
                //响应式拉取
                s.request(Integer.MAX_VALUE);
            }

            @Override
            public void onNext(String s) {
                Log.d(TAG,"onNext:"+s);
            }

            @Override
            public void onError(Throwable t) {

            }

            @Override
            public void onComplete() {
                Log.d(TAG,"onComplete:");
            }
        });

执行结果:

D/MainActivity: onNext:1
D/MainActivity: onNext:2
D/MainActivity: onComplete:

基本元素

  1. Flowable 被观察者,支持背压,和无背压版的Observable对应。
  2. Subscriber 观察者,作为Flowable的subscribe方法的参数。
  3. Subscription 支持背压,用于响应式拉取。
  4. FlowableOnSubscribe 当订阅时会触发此接口的调用。
  5. FlowableEmitter 发射器,用于发射数据。

跟着代码走
首先调用了Flowable的create方法,create方法接受两个参数,1、FlowableOnSubscribe匿名对象。2、背压策略 BackpressureStrategy.DROP
FlowableOnSubscribe是一个接口。

public interface FlowableOnSubscribe<T> {
    void subscribe(@NonNull FlowableEmitter<T> emitter) throws Exception;
}

背压策略使用的是枚举类型。有下面几种策略

public enum BackpressureStrategy {
    /**
     * OnNext事件的写入没有任何缓冲或丢弃。下游必须处理任何溢出。
     */
    MISSING,
    /**
     * 如果上游发的过快,下游的接收跟不上就通知MissingBackpressureException异常给下游
     */
    ERROR,
    /**
     * 缓存所有的上游数据,直到下游可以处理。
     */
    BUFFER,
    /**
     * 如果上游发的过快下游跟不上,就丢弃上游最近发送的数据
     */
    DROP,
    /**
     * 如果上游发的过快,下游跟不上,只保留最新发送的数据,覆盖之前任意的数据。
     */
    LATEST
}

为什么要有背压策略?通常当上下游处于不同的线程,上游发送的数据过快,但是下游处理的很慢,处理能力跟不上上游的发送速率。这时候就需要背压策略了,它是异步环境下产生的原因、发送和处理速度不统一、是一种流速控制解决策略。
继续看create方法,它做了什么呢?
Flowable#create()

    public static <T> Flowable<T> create(FlowableOnSubscribe<T> source, BackpressureStrategy mode) {
        
        return RxJavaPlugins.onAssembly(new FlowableCreate<T>(source, mode));
    }

可以看到Flowable#create()方法创建并返回了FlowableCreate对象,该对象持有匿名对象(source)和背压策略(mode)。RxJavaPlugins#onAssembly()方法在前面已经分析过,默认情况下它直接将参数返回。
紧接着调用FlowableCreate对象的subscribe方法并将观察者(Subscriber)对象传递进去,继续跟进发现subscribe()方法其实是FlowableCreate父类Flowable的方法。
Flowable#subscribe()

 public final void subscribe(Subscriber<? super T> s) {
        if (s instanceof FlowableSubscriber) {
            subscribe((FlowableSubscriber<? super T>)s);//1
        } else {
            ObjectHelper.requireNonNull(s, "s is null");
            subscribe(new StrictSubscriber<T>(s));
        }
    }

接着会走注释1代码,继续跟进
Flowable#subscribe()

public final void subscribe(FlowableSubscriber<? super T> s) {
       //...
        try {
            Subscriber<? super T> z = RxJavaPlugins.onSubscribe(this, s);//2
            subscribeActual(z);
        } 
        //...
    }

注释2处的代码不用管,默认返回的就是我们传进来的观察者s(z==s),接着调用subscribeActual(z)方法,将我们观察者对象直接传进去,Flowable的subscribeActual()方法是一个抽象方法,所以这里会执行到FlowableCreate的subscribeActual()方法,有没有发现思想和无背压是一样的?
当我们调用FlowableCreate的subscribe方法然后会将创建的观察者对象(Subscriber)传入subscribeActual()方法。
接着看看FlowableCreate的subscribeActual()方法干了什么?
FlowableCreate#subscribeActual()

public void subscribeActual(Subscriber<? super T> t) {
        BaseEmitter<T> emitter;
		//根据背压策略创建对应的发射器
        switch (backpressure) {
        case MISSING: {
            emitter = new MissingEmitter<T>(t);
            break;
        }
        case ERROR: {
            emitter = new ErrorAsyncEmitter<T>(t);
            break;
        }
        case DROP: {
            emitter = new DropAsyncEmitter<T>(t);//1
            break;
        }
        case LATEST: {
            emitter = new LatestAsyncEmitter<T>(t);
            break;
        }
        default: {
            emitter = new BufferAsyncEmitter<T>(t, bufferSize());
            break;
        }
        }

        t.onSubscribe(emitter);//2 调用观察者的onSubscribe方法
        try {
            source.subscribe(emitter);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            emitter.onError(ex); //出现异常就调用onError方法
        }
    }

首先是根据我们采取的背压策略创建对应的发射器,栗子中采取的是BackpressureStrategy.DROP,因此会创建创建DropAsyncEmitter对象作为发射器,该对象持有下游的观察者对象。

    static final class DropAsyncEmitter<T> extends NoOverflowBaseAsyncEmitter<T> {

        DropAsyncEmitter(Subscriber<? super T> downstream) {
            super(downstream);
        }
        //...
    }

然后在注释2直接调用了下游观察者的onSubscribe()方法,接着调用source的subscribe方法,并将持有下游观察者的发射器传进去,这个source就是我们的FlowableOnSubscribe匿名对象。

  Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
            	//调用发射器的onNext、onComplete方法
                emitter.onNext("1");
                emitter.onNext("2");
                emitter.onComplete();
            }
        }, BackpressureStrategy.DROP)

现在发射器传给subscribe方法了,因此,我们在它里面调用的一系列onNext方法和onComplete方法其实都是调用这个发射器的onNext方法、onComplete方法。我们可以猜想下,在这个发射器里面最终还是调用了下游观察者的onNext方法、onComplete方法,因为这个发射器是根据不同的背压策略创建的,所以它也负责了背压的工作,是不是呢,接着分析DropAsyncEmitter这个类。

   static final class DropAsyncEmitter<T> extends NoOverflowBaseAsyncEmitter<T> {

        private static final long serialVersionUID = 8360058422307496563L;

        DropAsyncEmitter(Subscriber<? super T> downstream) {
            super(downstream);
        }
    }

DropAsyncEmitter这个发射器代码就这点,在构造方法中直接将下游的观察者传给父类构造( super(downstream)),而且在DropAsyncEmitter这个类中也没有看到onNext、onComplete方法,继续跟踪父类看看。
DropAsyncEmitter#

   abstract static class NoOverflowBaseAsyncEmitter<T> extends BaseEmitter<T> {

        private static final long serialVersionUID = 4127754106204442833L;

        NoOverflowBaseAsyncEmitter(Subscriber<? super T> downstream) {
            super(downstream);
        }

        @Override
        public final void onNext(T t) {
            if (isCancelled()) { //如果被取消就直接返回
                return;
            }

            if (t == null) {
                onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
                return;
            }

            if (get() != 0) {	//1
                downstream.onNext(t);	//2
                BackpressureHelper.produced(this, 1);	//3
            } else {
                onOverflow(); //4
            }
        }

        abstract void onOverflow();
    }

重点看注释1、2、3的代码,再注释1处获取我们设置的值。这个值在哪里设置的呢?还记得响应式拉取的代码吗?

   Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                emitter.onNext("1");
                emitter.onNext("2");
                emitter.onComplete();
            }
        }, BackpressureStrategy.DROP)
                .subscribe(new Subscriber<String>() {
            @Override
            public void onSubscribe(Subscription s) {
                //响应式拉取
                s.request(Integer.MAX_VALUE);//设值
            }
            //...
        });

没错,就是在这里设置,如果我们没有调用s.request(Integer.MAX_VALUE);进行响应式拉取,它的值就为0,自然就不能进行onNext的操作了,在注释3处,每次发射了一次数据后都会将值进行减1操作,比如我们如果调用s.request(5);表示我们只拉取5个数据,将value设置为5,第一次get()肯定是5,然后发射第一条数据,再将value减1,下次再get时,value就为4了,当发射了5条数据之后,get()到的value肯定为0,此时后面的数据就无法onNext了,会走else中的代码onOverflow();onOverflow这个方法是一个抽象方法,由具体的发射器子类实现,在DropAsyncEmitter中他是一个空实现 。可以看到BackpressureStrategy.DROP这种背压策略的思想比较简单。至于get()获取value、s.request(5)设置value、BackpressureHelper.produced(this, 1)将value减1,他们所操作的value其实是AtomicLong类的,观察DropAsyncEmitter的继承结构可以发现DropAsyncEmitter间接继承了AtomicLong类。
AtomicLong介绍
AtomicLong是用于对Long类型进行操作的类,在32位操作系统中,64位的long变量会被JVM当作两个32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型,它提供了一些设值,更新值获取值的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值