RxJava执行流程和线程切换原理

RxJava在项目开发中用得还是比较多的,它能将复杂的嵌套调用转为链式调用,减轻代码的复杂性,方便于代码的后期维护工作。用得多了,自然想看下内部的实现原理,毕竟这么牛逼的框架,其内部的实现思想也是值得学习的,再者之前面试问到了RxJava的原理。所以这里就来记录下(代码基于2.x),也方便后续复习。


基本使用

Observable.just("1")
    .subscribe(object : Observer<String>{
         override fun onComplete() {}
         override fun onSubscribe(d: Disposable) {}
         override fun onNext(t: String) {}
         override fun onError(e: Throwable) {}
     })

上游可以通过Observable的操作符just发送事件,Observable有很多操作符,也可以根据业务需要自定义操作符。订阅观察者通过subscribe方法,它有多个重载方法,可以根据情况使用。上游发送的事件,下游就可以在onNext方法中获取结果。


执行原理

先看下RxJava的UML类图
在这里插入图片描述
明白了继承结构,接下来对上面的Demo进行原理分析

  • just()
public static <T> Observable<T> just(T item) {
   ObjectHelper.requireNonNull(item, "The item is null");
   return RxJavaPlugins.onAssembly(new ObservableJust<T>(item));  //1
}

Observable的just操作符在注释1处,会创建一个ObservableJust对象,参数为item。然后传入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;
}

默认情况下f为null,会直接返回source。也就是说还是会返回ObservableJust,它是抽象类Observable的子类。

  • subscribe()
public final void subscribe(Observer<? super T> observer) {
   ObjectHelper.requireNonNull(observer, "observer is null");
   try {
       observer = RxJavaPlugins.onSubscribe(this, observer);

       ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");

       subscribeActual(observer);  //1
   } catch (NullPointerException e) { // NOPMD
       throw e;
   } catch (Throwable e) {
    ...
   }
}

订阅方法subscribe它的实现在Observable中,而这个方法内部会调用subscribeActual方法。它是一个抽象方法,具体实现会在子类中。而刚刚调用just操作符返回了ObservableJust对象,所以subscribeActual具体实现在ObservableJust中

@Override
protected void subscribeActual(Observer<? super T> s) {
    ScalarDisposable<T> sd = new ScalarDisposable<T>(s, value);  //1
    s.onSubscribe(sd);  
    sd.run();  //2
}

这个s就是在使用时候创建的Observer对象,它会和value封装到ScalarDisposable中,然后在注释2调用run方法

@Override
public void run() {
    if (get() == START && compareAndSet(START, ON_NEXT)) {
        observer.onNext(value);  //1
        if (get() == ON_NEXT) {
            lazySet(ON_COMPLETE);
            observer.onComplete();  //2
        }
    }
}

在run方法中,注释1处会调用onNext方法,这样下游就可以收到事件了,回调onNext。事件发送完毕之后会发送onComplete通知发送完毕。


线程切换

对于RxJava用得比较多的地方就是做异步操作,比如数据库和网络请求,分析源码时候先写一个简单的使用

Observable.just("1")
        .subscribeOn(Schedulers.io())    //1
        .observeOn(AndroidSchedulers.mainThread())  //2   
        .subscribe(object : Observer<String>{ 
            override fun onComplete() {}
            override fun onSubscribe(d: Disposable) {}
            override fun onNext(t: String) {}
            override fun onError(e: Throwable) {}
        })

关键代码在注释1和2处,注释1让被观察者运行在io线程,注释2让观察者运行在主线程

先看注释1,跟进io()方法

public static Scheduler io() {
    return RxJavaPlugins.onIoScheduler(IO);
}

IO是一个静态变量,赋值代码为

IO = RxJavaPlugins.initIoScheduler(new IOTask());

这段代码最后是返回IoHolder.DEFAULT

 static final class IoHolder {
     static final Scheduler DEFAULT = new IoScheduler();
 }

最后返回的也就是IoScheduler对象,这个对象后面会用到,先记着

再来看subscribeOn方法

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

刚刚的IoScheduler传入这个方法,并传入ObservableSubscribeOn对象,构建返回给下一级调用。

再来看注释2,跟进mainThread()方法

private static final class MainHolder {
    static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));
}

private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
        new Callable<Scheduler>() {
            @Override public Scheduler call() throws Exception {
                return MainHolder.DEFAULT;
            }
        });

public static Scheduler mainThread() {
    return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
}

最后的MainHolder.DEFAULT是HandlerScheduler,并封装了一个主线程的Handler,这里就可以猜到线程切换就是通过Handler完成的。

两个线程切换的操作符分析完了,接着从整体调用流程来看RxJava的线程切换过程。整个流程代码切换过程分为三步

第一步,很简单,Observable->ObservableJust->ObservableSubscribeOn->ObservableObserveOn

第二步,订阅观察者,处理事件,通过subscribed()订阅观察者,内部会调用ObservableObserveOn的subscribeActual方法

@Override
protected void subscribeActual(Observer<? super T> observer) {
...
  Scheduler.Worker w = scheduler.createWorker();  //1
  source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize)); //2 
}

注释1处的scheduler是刚刚分析的HandlerScheduler对象,所以createWorker()方法的实现

public Worker createWorker() {
    return new HandlerWorker(handler);
}

w也就是HandlerWorker对象,封装到ObserveOnObserver中。

接着调用到ObservableSubscribeOn的subscribed,然后调用subscribeActual方法

@Override
public void subscribeActual(final Observer<? super T> s) {
    final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);  //1

    s.onSubscribe(parent);

    parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));  //2
}

这个方法里面的参数s就是ObserveOnObserver对象,注释1处会再对它封装,然后传入注释2处的SubscribeTask,它是一个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);
    }
}

然后看scheduleDirect方法,这里的scheduler就是IoScheduler,然后看下这个方法的实现,它的实现在父类Scheduler中

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

      final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);  //2

      DisposeTask task = new DisposeTask(decoratedRun, w);  //3

      w.schedule(task, delay, unit);  //4

      return task;
  }

先跟进这里的注释1,

public Worker createWorker() {
    return new EventLoopWorker(pool.get());
}

返回了一个EventLoopWorker对象

参数run就是SubscribeTask,它会被包装进DisposeTask对象,它也是一个Runnable对象。接着到注释4

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

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) {
        //1
            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;
}

关键代码在注释1处,参数run是会被封装到一个ScheduledRunnable对象中赋值为sr,然后放入一个线程池中,那么前面的SubscribeTask的run就会执行,代码切换到了子线程,再来回顾下它的run方法中

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

这个source是ObservableJust,它里面会调用到它的subscribeActual方法

protected void subscribeActual(Observer<? super T> s) {
    ScalarDisposable<T> sd = new ScalarDisposable<T>(s, value);
    s.onSubscribe(sd);
    sd.run();
}

s就是SubscribeOnObserver。事件处理完之后,就开始向下游发送事件

第三步

@Override
   public void onNext(T t) {
       actual.onNext(t);
   }

这个actual就是ObserveOnObserver,看下它的onNext方法

public void onNext(T t) {
...
    schedule();
}

void schedule() {
    if (getAndIncrement() == 0) {
        worker.schedule(this);
    }
}

这里的worker是HandlerWorker对象,跟进这个方法在HandlerWorker对象中的实现,

        @Override
        public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
            if (run == null) throw new NullPointerException("run == null");
            if (unit == null) throw new NullPointerException("unit == null");

            if (disposed) {
                return Disposables.disposed();
            }

            run = RxJavaPlugins.onSchedule(run);

            ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);

            Message message = Message.obtain(handler, scheduled);
            message.obj = this; // Used as token for batch disposal of this worker's runnables.

            handler.sendMessageDelayed(message, unit.toMillis(delay));

            // Re-check disposed state for removing in case we were racing a call to dispose().
            if (disposed) {
                handler.removeCallbacks(scheduled);
                return Disposables.disposed();
            }

            return scheduled;
        }

这里很明显的可以看到通过将Runnable封装到一个Message对象中,然后通过Handler向创建Handler所在线程发送了一个消息,这个Handler持有主线程的mainLooper,所以代码会切回主线程,后面的就是将事件在主线程发送给下游的onNext回调。

总结:线程切换被观察者是通过一个线程池切换到子线程,被观察者事件处理完之后,向下游发送事件,然后通过Handler切换回主线程。


执行流程

看完RxJava的原理,其实套路也明白了,上游在通过Observable调用不同操作符时候,返回的是Observable子类,再调用多个操作符时候,其实也是返回Observable子类,并且将上一个Observable对象传给下一个操作符,不同的操作符其功能是不同的,这样做的目的是为了适配多场景的使用。当遇到subscribe方法时候,用来订阅观察者。subscribe是在抽象类Observable中,它内部会调用subscribeActual方法,而不同的操作符返回的都是Observable的具体实现,它们都会实现subscribeActual方法。在这个方法内部也会对Observer包装,然后调用上一个Observable的subscribe方法,直到最上游,处理事件,然后向下游发送事件。举上面为例子,大致流程如下:
RxJava执行流程
使用别的操作符调用也是差不多这个理


参考

1.Rxjava的调用逻辑以及线程切换原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值