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

一、基础知识

RxJavaPlugins.onAssembly(new SingleJust<T>(item));
这个方法的作用设什么呢,其实它的作用就是一个转换作用。使用的hook技术,这里原理比较难懂 暂时理解成会转换成 new出来的对象吧。

/**
 * Calls the associated hook function.
 * @param <T> the value type
 * @param source the hook's input value
 * @return the value returned by the hook
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
@NonNull
public static <T> Single<T> onAssembly(@NonNull Single<T> source) {
    Function<? super Single, ? extends Single> f = onSingleAssembly;
    if (f != null) {
        return apply(f, source);
    }
    return source;
}

二、最简单的调用

Single.just("1")
      .subscribe(new SingleObserver<String>() {
          @Override
          public void onSubscribe(Disposable d) {

          }

          @Override
          public void onSuccess(String s) {

          }

          @Override
          public void onError(Throwable e) {

          }
      });

这段代码很简单的调用,里面的逻辑就是 Single.just 会产生一个SingleJust 对象然后调用父类的 subscribe 方法,在这个方法中最终还是调用的自己的subscribeActual 方法, 这个方法的参数是 SingleObserver 。

protected void subscribeActual(SingleObserver<? super T> s) {
    s.onSubscribe(Disposables.disposed());
    s.onSuccess(value);
}

最后得到结果就是SingleObserver 的onSubscribe 和 onSuccess 方法被调用。

三、加点难度 加入Map操作符以后是怎么调用呢?

Single.just("1")
        .map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) throws Exception {
                return Integer.valueOf(s);
            }
        })
        .subscribe(new SingleObserver<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {
            }
            @Override
            public void onSuccess(Integer integer) {
            }
            @Override
            public void onError(Throwable e) {
            }
        });

看看这个是如何回调成功呢?
首先还是创建一个SingleJust 调用map操作符,返回一个SingleMap 对象,然后调用去subscribe订阅 SingleObserver ,最终方法往回调用,到达 SingleMap 的 subscribeActual 并传入观察者对象SingleObserver。

source.subscribe(new MapSingleObserver<T, R>(t, mapper));

这里的source 是SingleJust , t是SingleObserver 对象 ,mapper 是map操作符传入的一个函数方法。

接下来看SingleJust的subscribe 如何调用的? 依然是父类的 subscribeActual传入的参数是 MapSingleObserver
最终调用了

protected void subscribeActual(SingleObserver<? super T> s) {
    s.onSubscribe(Disposables.disposed());
    s.onSuccess(value);
}

跟上一步一样调用了这个方法,只不过这里的观察者是MapSingleObserver。 看看它的onSubscribe 和 onSuccess 做了些什么事。

public void onSuccess(T value) {
    R v;
    try {
        v = ObjectHelper.requireNonNull(mapper.apply(value), "The mapper function returned a null value.");
    } catch (Throwable e) {
        Exceptions.throwIfFatal(e);
        onError(e);
        return;
    }
    t.onSuccess(v);
}

显示调用mapper的apply方法 也就是map 的那个转换操作的方法。 转换以后的值 作为的t的onSuccess 参数。也就是SingleObserver的onSuccess 被调用了。

小结一下:
在这里插入图片描述

1、从上到下调用过程中不停包装被观察者,显示SingleJust 然后到 SingleMap,soure就是自己上一层对象的引用
2、当遇到subscribe是 就一次调用每个被观察这的订阅功能, 显示SingleMap.subscribe(SingleObserver) 然后 把SingleObserver包装成MapSingleObserver 交给SingleJust 订阅, 一直到数据源位置,调用对象的onSubscribe ,onSuccess
3、从数据源 在一次调用每个被包装的 observer的onsuccess 方法,直到最后的 SingleObserver 的方法被调用

套路就是被观察者 (Single、Observable)没遇到一个操作符都把自己包装一层,然后用source 记录上一层的引用, 知道遇到subscribe 订阅方法,会创建一个观察者SingleObserver, 然后内部一次包装上一层的被观察这对象需要订阅的观察者。 如 SingleMap 订阅 SingleObserver,然后 SingleJust 订阅 MapSingleObserver 。 最后 调用终点的数据源的回调方法,onSuccess 。 在一次回调每一层的Observer 方法直到调用结束。

扫描二维码关注公众号,回复: 9639670 查看本文章

四、再加一点难度,加上线程操作符

Single.just("1")
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new SingleObserver<String>() {
            @Override
            public void onSubscribe(Disposable d) {
            }
            @Override
            public void onSuccess(String integer) {
            }
            @Override
            public void onError(Throwable e) {
            }
        });

为了理解起来不那么吃力,将map操作符暂时先去掉。

第一步 和第二步

根据 前面两节总结的套路,每次遇到操作符就创建对应的一个包裹被观察者,所以subscribeOn操作符 创建了 SingleSubscribeOn被观察者 ,然后 observeOn 创建了 SingleObserveOn被观察者。他们分别订阅了下一级穿过来的观察者。
SingleObserveOn 订阅了 SingleObserver, 并包装了一个 ObserveOnSingleObserver

// 这是SingleObserveOn 处理订阅的方法
protected void subscribeActual(final SingleObserver<? super T> s) {
    source.subscribe(new ObserveOnSingleObserver<T>(s, scheduler));
    // source 是SingleSubscribeOn 
}
//这是SingleSubscribeOn处理订阅的方法
protected void subscribeActual(final SingleObserver<? super T> s) {
    final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s, source);
    s.onSubscribe(parent);
    // 执行了线程切换,至于怎么线程切换先暂时不要关注,只是测试的parent ,如果在此订阅就是另外一个线程了,可以简单理解把parent 丢到另一个线程中了,执行了run方法
    Disposable f = scheduler.scheduleDirect(parent);
    parent.task.replace(f);
}

// 对应的查看SubscribeOnObserver 的run方法
    static final class SubscribeOnObserver<T>
    extends AtomicReference<Disposable>
    implements SingleObserver<T>, Disposable, Runnable {
        ...//一些其他的方法
        @Override
        public void run() {
            source.subscribe(this);
            //在线程中完成了订阅
        }
    }

按照订阅的执行顺序.subscribe -> observeOn -> subscribeOn -> just, 所以先是SingleObserveOn 订阅 SingleObserver,把SingleObserver包装成ObserveOnSingleObserver,交给SingleSubscribeOn订阅(启动了一个线程,在run方法中完成的订阅),并在包装一层得到一个 ObserveOnSingleObserver 交给 SingleJust进行 回调。

可以看到observeOn中并没有做任何操作,而subscribeOn 执行了一些特殊的代码。scheduler.scheduleDirect(parent)注释中我已经说明清楚。 所以到了SingleJust 数据源回调的时候,就是在newthread 线程中执行的。

第三步

执行从数据源开始执行回调,首页是SingleJust执行了onSuccess方法。 看一下 subscribeOn操作符创建被观察者SingleSubscribeOn 对应的观察者 ObserveOnSingleObserver的回调方法如何执行呢?

SubscribeOnObserver(SingleObserver<? super T> actual, SingleSource<? extends T> source) 
    this.actual = actual;
    this.source = source;
    this.task = new SequentialDisposable();
}
@Override
public void onSubscribe(Disposable d) {
    DisposableHelper.setOnce(this, d);
}
@Override
public void onSuccess(T value) {
    actual.onSuccess(value);
}
@Override
public void onError(Throwable e) {
    actual.onError(e);
}

这里的actual就是它的下一层 observeOn创建的被观察者 SingleObserveOn 对应的观察者 ObserveOnSingleObserver 执行回调方法了

ObserveOnSingleObserver(SingleObserver<? super T> actual, Scheduler scheduler) {
    this.actual = actual;
    this.scheduler = scheduler;
}
@Override
public void onSubscribe(Disposable d) {
    if (DisposableHelper.setOnce(this, d)) {
        actual.onSubscribe(this);
    }
}

@Override
public void onSuccess(T value) {
    //value 是从数据源一步步会掉回来的值
    this.value = value;
    //同样是完成了线程切换 但是它并没有执行下一步操作的回调。 如果不回调等于链条就断了,所以一定有回调,假设一下,线程切换执行就会在 run方法中执行回调
    Disposable d = scheduler.scheduleDirect(this);
    DisposableHelper.replace(this, d);
}

@Override
public void onError(Throwable e) {
    this.error = e;
    Disposable d = scheduler.scheduleDirect(this);
    DisposableHelper.replace(this, d);
}

@Override
public void run() {
    Throwable ex = error;
    if (ex != null) {
        actual.onError(ex);
    } else {
        //完成了线程操作以后, 执行run方法,然后继续回调
        actual.onSuccess(value);
        //actual 是 observeOn 创建的 SingleObserver ,至此我们就得到了想要的结果,回调链结束
    }
}

observeOn 的 onSuccess 方法中切换了线程 在对应的 run方法中完成的下一层的回调
actual 是 observeOn 创建的 SingleObserver ,至此我们就得到了想要的结果,回调链结束。
在这里插入图片描述

分析subscribeOn 和 observeOn是如何完成线程切换的

subscribeOn 对应的 SingleSubscribeOn 被观察者的订阅方法

protected void subscribeActual(final SingleObserver<? super T> s) {
    final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s, source);
    s.onSubscribe(parent);
    //parent作为一个
    Disposable f = scheduler.scheduleDirect(parent);
    parent.task.replace(f);
}
    public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
        final Worker w = createWorker();

        final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);

        DisposeTask task = new DisposeTask(decoratedRun, w);

        w.schedule(task, delay, unit);

        return task;
    }

从代码上看它创建了一个worker 然后执行了schedule , 因为我们newThread 对应是NewThreadWorker(猜的),看看它的schedule执行了什么。

    public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
        //run 就是 前面的parent 它是一个观察者(SubscribeOnObserver), 
        Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
        //继续对这个 Runnable进行包装
        ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);

        if (parent != null) {
            if (!parent.add(sr)) {
                return sr;
            }
        }

        Future<?> f;
        try {
            if (delayTime <= 0) {
                // 最后执行了submit  
                // executor ==    private final ScheduledExecutorService executor;
                // 执行了线程池 ,所以SubscribeOnObserver 的run就会被调用
                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;
    }

贴一下SubscribeOnObserver 的run方法

    static final class SubscribeOnObserver<T>
    extends AtomicReference<Disposable>
    implements SingleObserver<T>, Disposable, Runnable {
        
        @Override
        public void run() {
            //source 就是 SingleJust实例对象
            source.subscribe(this);
        }
    }

至此,subscribeOn 切换了订阅线程。 简单说让上一层的订阅在线程中执行。

observeOn 控制的是回调执行的线程,也就是 onSucess 或者 map操作符对应的函数方法执行的线程。
observeOn 对应的被观察者是 SingleObserveOn 对应的观察者是ObserveOnSingleObserver 所以我们直接去看看一下它的回调方法是如何执行的。

static final class ObserveOnSingleObserver<T> extends AtomicReference<Disposable>
implements SingleObserver<T>, Disposable, Runnable {

    ObserveOnSingleObserver(SingleObserver<? super T> actual, Scheduler scheduler) {
        this.actual = actual;
        this.scheduler = scheduler;
    }
    // 删掉了一些对于的方法
    @Override
    public void onSuccess(T value) {
        this.value = value;
        // 执行了线程操作,根据subscribeOn操作符的经验,这一句代码,主要是为了执行this 的润方法, 而run方法中正好是执行了对应的回调方法。
        Disposable d = scheduler.scheduleDirect(this);
        DisposableHelper.replace(this, d);
    }

    @Override
    public void run() {
        Throwable ex = error;
        if (ex != null) {
            actual.onError(ex);
        } else {
            actual.onSuccess(value);
        }
    }
  
}

看看scheduler.scheduleDirect

public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    final Worker w = createWorker();
    final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
    DisposeTask task = new DisposeTask(decoratedRun, w);
    w.schedule(task, delay, unit);
    return task;
}

一模一样的代码,创建一个worker 然后执行schedule,如何执行的?因为使用的是 AndroidSchedulers.mainThread() 所以对应的 Worker 猜测是HandlerScheduler 看看它的schedule

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

是不是特别熟悉 handler.sendMessageDelayed 发送消息到主线程去执行(猜的)。

看看 AndroidSchedulers.mainThread() 创建是什么 Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));主线程的handler 的包裹对象。
这个包裹对象被扔给了SingleObserveOn 被观察者,然后传递给了它对应的观察者 ObserveOnSingleObserver 最终执行了

public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    final Worker w = createWorker();
    final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
    DisposeTask task = new DisposeTask(decoratedRun, w);
    w.schedule(task, delay, unit);
    return task;
}

HandlerScheduler

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

所以最后实质就是调用了MainHandler的run方法。

发布了58 篇原创文章 · 获赞 16 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/dingshuhong_/article/details/99705348