RxJava切换线程是怎么实现的呢?

RxJava切换线程是怎么实现的呢?

lift变换过程

要明白 RxJava 切换线程切换线程的原理,我们首先得理解变换过程。
对于变换过程,我的理解就是:

Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(SubscriberString> subscriber) {
            subscriber.onNext("Hello");
            subscriber.onNext("Hi");
            subscriber.onNext("Aloha");
            subscriber.onCompleted();
        }
      })
      .observeOn(Schedulers.io())

      .map(new Function<String, List<String>>() {
        @Override
        public List<String> apply(String query) {
          return mCheeseSearchEngine.search(query);
        }
      })
      .observeOn(AndroidSchedulers.mainThread())

      .subscribe(new ConsumerString>>() {
        @Override
        public void accept(List<String> result) {
          showResult(result);
        }
      });

在上面的代码中,map 过程通过它的 apply 方法中把 String 转换为 List\ ,而这一点是 subscribe 无法做到的。

public final  Observable map(Func1 func) {
    return lift(new OperatorMap(func)); 
}

通过 map函数 的源码我们可以看出 map 函数直接调用了 lift 函数并且把我们的 func 传了进去,而 func 就是我们所做的具体变换操作。

// 注意:这段代码被我修改过部分参数,仅用于理解,源码并非如此。
public  Observable lift(Operator operator) {
    return Observable2.create(new OnSubscribe2() {
        @Override
        public void call(Subscriber subscriber1) {
            Subscriber subscriber2 = operator.call(subscriber1);
            subscriber2.onStart();
            onSubscribe1.call(subscriber2);
        }
    });
}

我们可以看到这里我们又创建了一个新的 Observable 对象,我们记为 Observable2,也就是说当我们执行 map 时,实际上返回了一个新的 Observable 对象,我们之后的 subscribe 函数实际上执行再我们新创建的 Observable2 上,这时他调用的就是我们新的 call 函数,也就是 Observable2 的 call 函数。最后 onSubscribe1.call(subscriber2) 的 onSubscribe1 就是我们 Observable1(原来的Observable) 保存的 onSubscribe1 对象,在OnSubscrib1中做一些回调操作,如subscriber2.next()。

接着我们看operator.call(subscriber1)的过程。

// 注意:这段代码也被我修改过。
public Subscriber call(final Subscriber subscriber1) { 
    return new Subscriber2(subscriber1) {
        @Override
        public void onNext(T t) {
            subscriber1.onNext(transformer.call(t)); 
        }
    };
}

这里的 transformer 就是我们在 map 调用是传进去的 func 函数,也就是变换的具体过程。到这里变换过程就此结束。我们总结一下,


如图所示,实际上我们通过 lift 创建了一个新的对象 Observable2 ,我们之后的 subscribe 实际上执行在了它身上。operator执行了之前 Observable1 的 call 函数,并且创建了一个新的对象 Subscriber2 ,它的作用就是接受原来 Observable1 的事件 func ,然后经过转换,传递给最终的 Subscriber1,执行它的 onNext 函数。我们这样就跑通了变换的整个逻辑了,我们也可以发现这个逻辑类似于拦截,通过拦截 subscribe 函数,再把 Observable1 的 subscribe 拦截到新的 Subscriber2 对象中来执行,从而实现转换的逻辑。

线程切换

RxJava 最好用的特点就是��供了方便的线程切换,但它的原理归根结底还是 lift。subscribeOn() 和 observeOn() 都做了线程切换的工作(图中的 “schedule…” 部位)。不同的是, subscribeOn() 的线程切换发生在 OnSubscribe 中,即在它通知上一级 OnSubscribe 时,这时事件还没有开始发送,因此 subscribeOn() 的线程控制可以从事件发出的开端就造成影响。

subscribeOn() 原理图

observeOn() 原理图

为什么 subscribeOn()只有第一个有效?

举个例子,subscribeOn2从通知开始将后面的执行全部投递到需要的线程2来执行,但是之后的投递会受到在subscribeOn2的上级subscribeOn1的的影响,subscribeOn1又会把执行投递到线程1中去,这样执行就不受到subscribeOn2的控制了。所以只有第一个subscribeOn有效。

图中共有 5 处含有对事件的操作。由图中可以看出,①和②两处受第一个 subscribeOn() 影响,运行在红色线程;③和④处受第一个 observeOn() 的影响,运行在绿色线程;⑤处受第二个 onserveOn() 影响,运行在紫色线程;而第二个 subscribeOn() ,由于在通知过程中线程就被第一个 subscribeOn() 截断,因此对整个流程并没有任何影响。这里也就回答了前面的问题:当使用了多个 subscribeOn() 的时候,只有第一个 subscribeOn() 起作用。

你可能感兴趣的:(琐碎知识点)