RxJava 的链路调用流程

  • 一、概述
  • 二、基本使用方法
  • 三、Observable 链路调用流程分析
  • 1. testCreate() 方法的调用流程
  • 2. testJust() 方法的调用流程
  • 四、小结


一、概述

RxJava 是一个响应式编程框架,里面代码比较复杂,本系列文章将从以下几个角度来分析这个框架。

  1. RxJava 的链路调用流程。
  2. RxJava 的常用操作符 map、flatmap
  3. RxJava 的线程调度。
  4. 自己实现一个简易版的 RxJava 框架。
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.19'

二、基本使用方法

我们知道, RxJava 的设计也是基于 观察者模式 的,所以里面存在两个角色,一个是观察者Observer,另一个是被观察者Subject

下面我们来看看在 RxJava 中常见的构造 Subject 对象的方法。(在 RxJava 中,Subject 对应的是 Obserable、Flowable 等。

Obserable.create(ObservableOnSubscribe<T> source)
Obserable.just(T item)
Obserable.fromArray(T... items)
Obserable.zip()
...等等...

下面我们来看看 Obserable 的具体使用示例。

private void testCreate() {
    Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> emitter) throws Exception {
            emitter.onNext("1");
            emitter.onNext("2");
            emitter.onNext("3");
            emitter.onComplete();
        }
    }).subscribe(new Observer<String>() {
        @Override
        public void onSubscribe(Disposable d) {}

        @Override
        public void onNext(String s) {
            Log.d(TAG, "onNext = " + s + "; Type = " + s.getClass().getSimpleName());
        }

        @Override
        public void onError(Throwable e) {}

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

private void testJust() {
    Observable.just("11", "22", "33")
        .map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) throws Exception {
                return Integer.parseInt(s);
            }
        })
        .subscribeOn(Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<Integer>() {
	        @Override
	        public void onSubscribe(Disposable d) {}
	
	        @Override
	        public void onNext(Integer s) {
	            Log.d(TAG, "onNext = " + s + "; Type = " + s.getClass().getSimpleName());
	        }
	
	        @Override
	        public void onError(Throwable e) {}
	
	        @Override
	        public void onComplete() {
	            Log.d(TAG, "onComplete");
	        }
	    });
}

testCreate() 输出日志:

onNext = 1 ; Type = String
onNext = 2 ; Type = String
onNext = 3 ; Type = String
onComplete

testJust() 输出日志:

onNext = 11 ; Type = Integer
onNext = 22 ; Type = Integer
onNext = 33 ; Type = Integer
onComplete

下面我们就根据 testCreate()、testJust() 两个方法来分析一下 Observable 链路调用流程。


三、Observable 链路调用流程分析

下面我们先来分析一下 testCreate() 的调用链路。

1. testCreate() 方法的调用流程

testCreate() 方法主要分为两步:

  1. 通过 Observable.create() 方法构建一个 Observable 对象。
  2. 通过 Observable.subscribe() 将观察者 Observer 关联到 Observable 上。

Observable

public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
    ObjectHelper.requireNonNull(source, "source is null");
    // 1.这里会构建一个 ObservableCreate 类,将外部真正的数据发射源 source 保存在 ObservableCreate 中。
    return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}

// 2.调用这个 subscribe 方法的类其实是上一布创建的 ObservableCreate 类。
public final void subscribe(Observer<? super T> observer) {
    ObjectHelper.requireNonNull(observer, "observer is null");
    try {
        observer = RxJavaPlugins.onSubscribe(this, observer);
        // 3.调用 ObservableCreate.subscribeActual() 方法,这个observer是我们外部真正的接收者.
        subscribeActual(observer);
    } catch (NullPointerException e) { // NOPMD
        // ...省略异常处理的代码...
    }
}

小结:

  1. 调用 Observable.create() 会创建一个 ObservableCreate 对象。
  2. 调用 ObservableCreate.subscribe() 后会触发 ObservableCreate.subscribeActual() 分发,该方法会将用户创建的 Observer 和 ObservableCreate 关联起来。

下面我们看一下 ObservableCreate.subscribeActual() 方法。

ObservableCreate

public ObservableCreate(ObservableOnSubscribe<T> source) {
	// 这个 source 是外部用户创建的对象。
    this.source = source;
}

// 此处的接收参数 observer 是外部用户创建的接收者。
protected void subscribeActual(Observer<? super T> observer) {
	// 1.将外部用户创建的接收者包装起来,返回一个包装类 CreateEmitter。
    CreateEmitter<T> parent = new CreateEmitter<T>(observer);
    // 2.执行接收者的 onSubscribe 方法。
    observer.onSubscribe(parent);

    try {
        // 3.source 是外部用户创建的发射数据源,将 source 与包含有接收者的 CreateEmitter 进行关联。
        source.subscribe(parent);
    } catch (Throwable ex) {
        Exceptions.throwIfFatal(ex);
        parent.onError(ex);
    }
}

由上面代码可知,source 就是我们下面这段代码创建的 ObservableOnSubscribe 对象。而 ObservableOnSubscribe.subscribe() 方法接收的参数就是 CreateEmitter 对象,然后我们会调用 CreateEmitter.onNext() 方法。

private void testCreate() {
    Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> emitter) throws Exception {
            emitter.onNext("1");
            emitter.onNext("2");
            emitter.onNext("3");
            emitter.onComplete();
        }
    }).subscribe(new Observer<String>() { 
    	//略 
    });
}

下面我们来看一下 CreateEmitter.onNext() 方法到底做了什么?

CreateEmitter

static final class CreateEmitter<T> extends AtomicReference<Disposable> 
		implements ObservableEmitter<T>, Disposable {

	// 这个 observer 是我们用户态创建的接收者。
    final Observer<? super T> observer;

    CreateEmitter(Observer<? super T> observer) {
        this.observer = observer;
    }

	// 这个onNext方法是在用户态去触发的
    @Override
    public void onNext(T t) {
        if (!isDisposed()) {
            observer.onNext(t); //这里其实执行了用户态的observer接收者的onNext方法。
        }
    }
    
    // 这个onNext方法是在用户态去触发的
    @Override
    public void onComplete() {
        if (!isDisposed()) {
            try {
            	//这里其实执行了用户态的observer接收者的onComplete方法。
                observer.onComplete(); 
            } finally {
                dispose();
            }
        }
    }
}

小结:

Rxjava 串联任务_Rxjava 串联任务


如上图所示,完整的 testCreate() 调用链路分为8个步骤:

  1. 在执行 Observable.create() 方法时,会先创建一个 ObservableOnSubscribe 对象。
  2. 然后通过 Observable.create() 方法会创建出一个 ObservableCreate 对象。
  3. 调用 ObservableCreate.subscribe() 方法时,会先创建一个 Observer 对象。
  4. 将步骤3创建的 Observer 对象通过 ObservableCreate.subscribe() 方法赋值给 ObservableCreate 对象。
  5. 在调用 ObservableCreate.subscribe() 方法时,实际会调用 ObservableCreate.subscribeActual() 方法,该方法内会创建一个 CreateEmitter 对象,该对象其实是给用户调用的。
  6. 调用 ObservableOnSubscribe.subscribe() 方法,将 CreateEmitter 对象作为参数传递出去。
  7. 用户在 ObservableOnSubscribe.subscribe() 方法中调用 CreateEmitter.onNext() 方法,将数据源发射出来。
  8. 由于 CreateEmitter 内持有用户创建的Oberver,所以在 CreateEmitter.onNext() 方法中会调用 Observer.onNext() 方法,完成用户的数据处理。

2. testJust() 方法的调用流程

示例代码:

private void testJust() {
    Observable.just("11", "22", "33")
        .map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) throws Exception {
                return Integer.parseInt(s);
            }
        })
        .subscribeOn(Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<Integer>() { 
        	//略 
        });
}

testJust() 方法包含了以下几个操作:

  1. 元素的发送: just() 操作符
  2. 类型的转换: map() 操作符
  3. 线程的切换: subscribeOn()、observeOn() 操作符
  4. 元素的接收: subscribe() 操作符

Observable.just()

public static <T> Observable<T> just(T item1, T item2, T item3) {
	// 1.接收多个事件的发送。
    return fromArray(item1, item2, item3);
}

public static <T> Observable<T> fromArray(T... items) {
    ObjectHelper.requireNonNull(items, "items is null");
    if (items.length == 0) {
        return empty();
    }
    if (items.length == 1) {
        return just(items[0]);
    }
    // 2.将接收到的多个事件包装在一个ObservableFromArray中。
    return RxJavaPlugins.onAssembly(new ObservableFromArray<T>(items));
}

调用 Observable.just() 方法后,返回的是 ObservableFromArray 对象。

ObservableFromArray.map()

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));
}

调用 Observable.map() 方法后,返回的是 ObservableMap 对象,关于 map 操作符的逻辑,都在 ObservableMap 对象里。

ObservableFromArray.subscribeOn()

public final Observable<T> subscribeOn(Scheduler scheduler) {
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}

调用 Observable.subscribeOn() 方法后,返回的是 ObservableSubscribeOn 对象,关于 subscribeOn 操作符的逻辑,都在 ObservableSubscribeOn 对象里。

ObservableFromArray.observeOn()

public final Observable<T> observeOn(Scheduler scheduler) {
    return observeOn(scheduler, false, bufferSize());
}

public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    ObjectHelper.verifyPositive(bufferSize, "bufferSize");
    return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
}

调用 Observable.observeOn() 方法后,返回的是 ObservableObserveOn 对象,关于 observeOn 操作符的逻辑,都在 ObservableObserveOn 对象里。

小结:
如下图所示,完整的 testJust() 调用链路分为三个部分:

  1. 创建任务链。 如下图红色流程,每调用一个操作符都会返回一个与之对应的 Observable 对象。
  2. 逆向逐级订阅。 如下图粉色流程,每一步都会生成一个对应的 Observer 对上一步生成的Observable进行订阅。
  3. 执行任务链。 如下图绿色流程,执行任务链之后,每一步都会通知对应的 Observer.onNext(),从而完成整调任务链。

Rxjava 串联任务_Rxjava 串联任务_02

四、小结

  1. 如何查看 RxJava 的源码?
  1. 学会查看 RxJava 的调用链是如何串联起来的。
  2. 知道每个操作符的逻辑在哪里查看。
  1. RxJava 的调用链是如何串联起来的?

主要通过三个流程将调用链串联起来:

  1. 创建任务链。 每调用一个操作符都会返回一个与之对应的 Observable 对象。
  2. 逆向逐级订阅。 每一步都会生成一个对应的 Observer 对上一步生成的Observable进行订阅。
  3. 执行任务链。 执行任务链之后,每一步都会通知对应的 Observer.onNext(),从而完成整调任务链。
  1. 每个操作符的逻辑在哪里查看?

我们知道,每调用一个操作符都会返回一个与之对应的 Observable 对象。因此每个操作符的处理逻辑都写在这个新生成的 Observable 对象中,如调用 map 操作符,则该操作符的处理逻辑就在 ObservableMap 中。