RxJava原理分析

1.Rxjava的基本订阅流程,上游 Observable和下游上游 Observable的概念

1.1基本概念

observable和observer通过subscribe方法实现了订阅关系,在需要的时候observable发送事件来通知observer,并且回调observer的相关方法 。

Observable:被观察者

Observer:观察者

sbscribe:订阅,将观察者和被观察者关联起来

事件:onNext,onComplete,onError

典型示例:

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) {
            Log.e("TAG", "onSubscribe():  ");
        }

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

        @Override
        public void onError(Throwable e) {

        }

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

输出结果:
E/TAG: onSubscribe():  
E/TAG: onNext():  1
E/TAG: onNext():  2
E/TAG: onNext():  3
E/TAG: onComplete():

1.2Observable#subscribe(Observer) 订阅流程解析

直接 Observable.subscribe的源代码:

public final void subscribe(Observer<? super T> observer) {
    //**********略**********
    //关键代码--移步 ObservableCreate.subscribeActual
    subscribeActual(observer);
    //**********略**********
}

但是subscribeActual是一个抽象方法,它的具体实应该在子类中实现,到底是哪个子类可以在create方法中知道是在子类ObservableCreate中完成的:

public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
    //********略
    //调用hook关联方法,实际要去看ObservableCreate类
    return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}

打开ObservableCreate找到subscribeActual方法

/**
 * 这里面只做了两件事:
 * 1.将下游传过来的observer封装
 * 2.让上游的source也就是observable来subscribe传进来的observer
 **/
protected void subscribeActual(Observer<? super T> observer) {
    //将observer传给observable,但是在observable中又会在onNext方法中激活observer的onNext方法。
    CreateEmitter<T> parent = new CreateEmitter<T>(observer);
    //方法一:触发 Observer#onSubscribe(Disposable),最先被调用的。
    observer.onSubscribe(parent);

    try {
        //方法二:发射事件,这个方法一般是由我们自己去实现的,调用onNext和onComplete。
        // source为上游observable(上游ObservableOnSubscribe的引用),
        // 在所有的onservable的子类实现中都有一个source字段,指代上游observable
        source.subscribe(parent);
    } catch (Throwable ex) {
        Exceptions.throwIfFatal(ex);
        parent.onError(ex);
    }
}

在这里需要关注source这个成员,其实它就是我们自定义的ObservableOnSubscribe赋值给它了,在所有的onservable的子类实现中都有一个source字段指代上游observable。可以看到subscribeActual里面主要有两个方法:observer.onSubscribe(parent)和source.subscribe(parent),onSubscribe很好理解,source.subscribe一般是我们自己实现的:

@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
      emitter.onNext("1");
      emitter.onNext("2");
      emitter.onNext("3");
      emitter.onComplete();
  }

在这里我们调用CreateEmitter的onNext和onComplete方法,跟到CreateEmitter里面看下这两个方法的具体实现

@Override
public void onNext(T t) {
    //********省略
    //当不处于DISPOSED状态时,会调用下游observer的onNext方法,
    //下游observer就是我们自己实现的onNext回调
    if (!isDisposed()) {
        observer.onNext(t);
    }
}

很明显这里会调用subscribeActual方法传进来的下游observer.onNext方法,其实就是我们示例中的实现的onNext。总结下:基本订阅流程是从subscribeActual开始的,将observer传递给observable,在observable中上游ObservableOnSubscribe调用subscribe时会调用onNext方法,这时候又会激活observer的onNext方法。这里面是一个链式调用,Observable#subscribeActual(Observer)实现中都包含有一句source.subscribe(Observer),其中source就是上游 Observable,所以就可以理解在每一个Observable的subscribeActual(Observer) 方法中它都会调用上游的subscribe(Observer)/subscribeActual(Observer) 方法,直至到达第一个Observable的subscribe(Observer)/subscribeActual(Observer)中。

1.3Observer#onSubscribe(Disposable) 流程

onSubscribe的过程正好和subscribe相反,当订阅到达最顶端的时候已经没办法继续往上传递了,这时候会调用最顶层observable的subscribe方法也就是subscribeActual:

CreateEmitter<T> parent = new CreateEmitter<T>(observer);
observer.onSubscribe(parent);

它首先封装了一个 Disposable,接下来将调用 Observer#onSubscribe(Disposable) 将 Disposable 作为参数传给下一层 Observer,到了下一层的Observer的onSubscribe(Disposable)中该方法中针对上一层Disposable做一些操作(判断、封装等),然后再封装一个 Disposable作为参数传递给下一层observer直至最底层,最底层的observer就是我们自己实现的。

1.4Observer#onNext(T) 流程

onNext流程跟onSubscribe比较类似,顶游Observable会触发ObservableEmitter#onNext(T)方法,在该方法的内部又触发了「下游」Observer的onNext(T) 方法,而在该方法内部又会触发「下游的下游」Observer的onNext(T)方法,直至最底层的Observer我们所自定义的 Observer。

2.Rxjava切换线程

2.1Observable#subscribeOn(Scheduler)控制线程切换

2.1.1 下游决定上游的执行线程

直接查看Observable.subscribeOn源代码

public final Observable<T> subscribeOn(Scheduler scheduler) {
    // scheduler 判空
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    // 用 ObservableSubscribeOn 将 scheduler 包装 起来
    return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}

下面我们直接跟到ObservableSubscribeOn.subscribeActual即可,遮里面同样有一个source成员类型是ObservableSource,这个类指的是上游observable,和 ObservableCreate套路是一样的。

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 SubscribeTask(parent)));
    }
    //略---
}

除了source还有另外一个成员Scheduler,初始化有两种方法:Schedulers.newThread()或者Schedulers.io() 。现在重点跟进parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent))),先看看SubscribeTask这个类是ObservableSubscribeOn 的一个非静态内部类,逻辑比较简单实现了Runnable接口,并且持有parent的引用。

final class SubscribeTask implements Runnable {
    private final SubscribeOnObserver<T> parent;

    SubscribeTask(SubscribeOnObserver<T> parent) {
        this.parent = parent;
    }

    @Override
    public void run() {
        source.subscribe(parent);
    }
}

重点关注run方法,通过source.subscribe(parent)建立联系,因此当我们的SubscribeTask的run方法运行在哪个线程,相应的observer的subscribe方法就运行在哪个线程。接下来看一下scheduler.scheduleDirect这个方法:

/**
**首先,创建一个 Worker w
**第二步,DisposeTask 将 decoratedRun 包装起来
**第三步:w 去调度 task
**/
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    final Worker w = createWorker();
    // 判断 run 是否为 null
    final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
    DisposeTask task = new DisposeTask(decoratedRun, w);
    w.schedule(task, delay, unit);
    return task;
}

再继续跟进Worker看看里面的实现,很清晰里面就是封装了一个线程池

public Worker createWorker() {
    return new NewThreadWorker(threadFactory);
}

public class NewThreadWorker extends Scheduler.Worker implements Disposable {
    private final ScheduledExecutorService executor;

    volatile boolean disposed;

    public NewThreadWorker(ThreadFactory threadFactory) {
        executor = SchedulerPoolFactory.create(threadFactory);
    }
}

public static ScheduledExecutorService create(ThreadFactory factory) {
    final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, factory);
    if (PURGE_ENABLED && exec instanceof ScheduledThreadPoolExecutor) {
        ScheduledThreadPoolExecutor e = (ScheduledThreadPoolExecutor) exec;
        POOLS.put(e, exec);
    }
    return exec;
}

总结:

在 ObservableSubscribeOn subscribeActual 方法中, SubscribeTask 包装 parent(SubscribeOnObserver,包装了 Observer),SubscribeTask 实现了 Runnable 接口,在 run 方法里面调用了 source.subscribe(parent),因而 run 方法所执行的线程将由 worker 决定。这就是 下游决定上游 observable 执行线程的原理

2.1.2线程切换第一次有效原理

来个例子两次subscribeOn,日志:subscribe: getName=RxCachedThreadScheduler-1,如果调换两次subscribeOn的顺序日志为:subscribe: getName=RxComputationThreadPool-1

Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
        Log.i(TAG, "subscribe: getName=" +Thread.currentThread().getName());
    }
}).subscribeOn(Schedulers.io())//第一次subscribeOn
.subscribeOn(Schedulers.computation())//第二次subscribeOn
.subscribe(new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {
        Log.e("TAG", "onSubscribe():  ");
    }

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

    @Override
    public void onError(Throwable e) {

    }

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

来解释下为什么第一次subscribeOn有效,上面分析中可以知道Obsevable#subscribeOn(Scheduler)这个方法的实质其实就是将Observable#subscribe(Observer)放到指定的线程中来执行,执行Observable#subscribe的时候是自下往上的,下游observable调用上游observable,对于上面的例子流程是这样的:

(1)第三个Observable调用Observable#subscribe(Observer)启动订阅,在其内部会激活第二个Observable的Observable#subscribe(Observer)方法,但是此时该方法外部被套入了一个 Schedulers.computation() 线程

public class Observable {
    // 第「二」个 Observable
    Observable source;
    Observer observer;

    public Observable(Observable source, Observer observer) {
        this.source = source;
        this.observer = observer;
    }

    public void subscribe(Observer Observer) {
        new Thread("computation") {
            @Override
            public void run() {
                // 第「二」个 Observable 订阅
                source.subscribe(observer);
            }
        }
    }
}

(2)第二个Observable订阅内部会激活第一个Observable的Observable#subscribe(Observer)方法,同样的,该方法被套在了Schedulers.io()线程中

public class Observable {
    // 第「一」个 Observable
    Observable source;
    Observer observer;

    public Observable(Observable source, Observer observer) {
        this.source = source;
        this.observer = observer;
    }

    public void subscribe(Observer Observer) {
        new Thread("io") {
            @Override
            public void run() {
                // 第「一」个 Observable 订阅
                source.subscribe(observer);
            }
        }
    }
}

(3)第一个observable就是我们自己实现的,这里就要开始发射事件了,这两层嵌套如下可以很明显的看出为什么会第一次有效:

new Thread("computation") {
    @Override
    public void run() {
        // 第二个 Observable.subscribe(Observer) 的实质
        // 就是切换线程,效果类似如下
        new Thread("io") {
            @Override
            public void run() {
                // 第一个 Observable.subscribe(Observer) 的实质
                // 就是发射事件
                System.out.println("onNext(T)/onError(Throwable)/onComplete() 的执行线程是: " + Thread
                                   .currentThread().getName());
            }
        } .start();
    }
} .start();

2.2Observable#observeOn(Scheduler)

重述一下订阅过程:当我们调用 Observable 的 subsribe 方法的时候,会调用当前对应 observbale 的 subscribeActual 方法,在该方法里面,会调用 observer 的 onSubeciber 方法,并调用对应 ObservableOnSubscirbe 的 subcribe 的方法,并将 ObservableEmitter 作为方法参数暴露出去。而 ObservableEmitter 持有我们的 Observer 的引用,当我们调用 ObservableEmitter 的 onNext,onErrot,onComplete 方法的时候,会调用他持有的 Observer 的相应的方法。

直接看observeOn的源码:

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.create非常的类似,内部有持有上游observable的source成员,直接来看ObservableObserveOn的subscribeActual方法即可:

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 {
            //否则,通过worker包装observer另起个线程的形式调用
            Scheduler.Worker w = scheduler.createWorker();
            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
        }
    }
}

2.2.1不作用上游observable

看上面的这行代码source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));source为上游observable,可见上游observable没有任何变化只是对下游observable进行了封装,这行代码解释了不作用上游observable。

2.2.2.作用下游observable

还是source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));这行代码,对下游observer进行了封装成为ObserveOnObserver对象。在订阅流程中可以知道发射事件时最终会触发下游observer的onNext方法,现在跟进到ObserveOnObserver的onNext中:

public void onNext(T t) {
    if (done) {
        return;
    }
    if (sourceMode != QueueDisposable.ASYNC) {
        queue.offer(t);
    }
    schedule();
}

做了两件事将一是传进的对象添加进队列,二是调用schedule()方法,跟进schedule方法:

void schedule() {
    if (getAndIncrement() == 0) {
        //这里传进去的是this,直接导致worker.schedule最终会执行
        //ObserveOnObserverde的run方法。
        worker.schedule(this);
    }
}

schedule方法最终可以追溯到Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit)抽象方法,找一个它的实现类IoScheduler打开它的schedule方法:

public Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull TimeUnit unit) {
    if (tasks.isDisposed()) {
        // don't schedule, we are unsubscribed
        return EmptyDisposable.INSTANCE;
    }
    return threadWorker.scheduleActual(action, delayTime, unit, tasks);
}

继续跟进threadWorker.scheduleActual:

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

executor是ScheduledExecutorService实例,这个比较熟悉具有调度线程的能力。串一下流程:onNext(T)方法会触发Scheduler对象的schedule(Runnable, long, TimeUnit)方法是一个抽象方法由子类实现,所以才有了多元多样的Schedulers.io()/Schedulers.computation()/Schedulers.trampoline()等调度器。上面说过worker最终是会执行ObserveOnObserver的run方法的,回过头来看一下ObserveOnObserver的run方法:

public void run() {
    if (outputFused) {
        drainFused();
    } else {
        drainNormal();
    }
}

选择一个方法的代码跟(两个比较类似)跟进drainNormal:

void drainNormal() {
    int missed = 1;
    final SimpleQueue<T> q = queue;
    final Observer<? super T> a = downstream;
    for (;;) {
        if (checkTerminated(done, q.isEmpty(), a)) {
            return;
        }
        for (;;) {
            boolean d = done;
            T v;
            try {
                v = q.poll();
            } catch (Throwable ex) {
                Exceptions.throwIfFatal(ex);
                disposed = true;
                upstream.dispose();
                q.clear();
                a.onError(ex);
                worker.dispose();
                return;
            }
            boolean empty = v == null;
            if (checkTerminated(d, empty, a)) {
                return;
            }
            if (empty) {
                break;
            }
            a.onNext(v);
        }
        missed = addAndGet(-missed);
        if (missed == 0) {
            break;
        }
    }
}

稍微分析这段代码可以看到最终是执行下游observer的onNext方法(a.onNext(v)),什么意思呢,也就是说ObserveOnObserver中触发的下游observer的onNext方法在指定线程执行了,也就是达到了回调切换线程的目的了。

2.2.3举个例子说明一下

Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
        emitter.onNext("1");
    }
})//第一个observable
.observeOn(Schedulers.io())//第二个observable
.flatMap(new Function<String, String>(){
    @override
    public String apply(String s) throws Exception{
        return s;
    }
})
.observeOn(Schedulers.computation())//第三个observable
.subscribe(new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {
        Log.e("TAG", "onSubscribe():  ");
    }

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

    @Override
    public void onError(Throwable e) {

    }

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

从订阅流程可知observer的传递是从下往上的,首先observer向上传递到达第三个observable的时候进行了一次线程切换被computation 线程嵌套了一层:

public class Observer {
    Observer oldObserver;
    public Observer(Observer observer) {
        oldObserver = observer;
    }

    public void onNext(T t) {
        // 一些其他操作
        new Thread("computation") {
            @Override
            public void run() {
                oldObserver.onNext(t);
            }
        } .start();
    }

    public void onError(Throwable e) {
        // 一些其他操作
        new Thread("computation") {
            @Override
            public void run() {
                oldObserver.onError(e);
            }
        } .start();
    }

    public void onComplete() {
        // 一些其他操作
        new Thread("computation") {
            @Override
            public void run() {
                oldObserver.onComplete();
            }
        } .start();
    }
}

observer继续向上传递到达第二个observable的时候又进行了一次切换,被io线程嵌套了一层:

public class Observer {
    Observer oldObserver;
    public Observer(Observer observer) {
        oldObserver = observer;
    }

    public void onNext(T t) {
        // 一些其他操作
        new Thread("androidIO") {
            @Override
            public void run() {
                oldObserver.onNext(t);
            }
        } .start();
    }

    public void onError(Throwable e) {
        // 一些其他操作
        new Thread("androidIO") {
            @Override
            public void run() {
                oldObserver.onError(e);
            }
        } .start();
    }

    public void onComplete() {
        // 一些其他操作
        new Thread("androidIO") {
            @Override
            public void run() {
                oldObserver.onComplete();
            }
        } .start();
    }
}

最终到达最顶层第一个observable,简而言之 Observable#observeOn(Scheduler) 的实现原理在于将目标 Observer 的 onNext(T)/onError(Throwable)/onComplete() 置于指定线程中运行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值