通过源码来理解RxJava是切换到主线程的?

转载请注明出处,谢谢https://blog.csdn.net/HarryWeasley/article/details/105363078

下方是一个最简单切换线程的方式,本篇文章以下方的代码引入。

 Observable.create(new ObservableOnSubscribe<String>() {
                    @Override
                    public void subscribe(ObservableEmitter<String> e) throws Exception {
                        e.onNext("1");
                        e.onNext("2");
                        e.onComplete();
                    }
                })
                        //切换到子线程
                        .subscribeOn(Schedulers.io())
                        //切换主线程
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Observer<String>() {
                            @Override
                            public void onSubscribe(Disposable d) {

                            }

                            @Override
                            public void onNext(String value) {
                                Log.d(TAG, "this is result"+value);
                            }

                            @Override
                            public void onError(Throwable e) {

                            }

                            @Override
                            public void onComplete() {

                            }
                        });

如上的代码,当我们调用了observeOn(AndroidSchedulers.mainThread())这句话,就切换了到主线程,现在跟着源码看看,rxJava是如何操作的。
Observable类:

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

public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
    //检查schedule是否为null
        ObjectHelper.requireNonNull(scheduler, "scheduler is null");
        //检查bufferSize是否大于0,默认是128
        ObjectHelper.verifyPositive(bufferSize, "bufferSize");
        return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
    }

进入到RxJavaPlugins.onAssembly这个方法中
RxJavaPlugins类:

public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
//这里是个hook机制,onObservableAssembly默认是null
        Function<? super Observable, ? extends Observable> f = onObservableAssembly;
        if (f != null) {
            return apply(f, source);
        }
        //f为null,直接返回source,这里是ObservableObserveOn
        return source;
    }

注释已经写明了,所以我们直接看传入的ObservableObserveOn
ObservableObserveOn类:

 //本例是 AndroidSchedulers.mainThread()
    final Scheduler scheduler;
    ...
    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,这里是重点1
            Scheduler.Worker w = scheduler.createWorker();
            //用ObserveOnObserver订阅上游数据源。这样当数据从上游push下来,会由ObserveOnObserver对应的onXXX()处理
            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
        }
    }

这里有个重点需要注意一些scheduler.createWorker(),返回了一个worker,之后会进行解释。

现在,我们看下ObserveOnObserver类的部分方法,还是那句话,本篇文章,主要是查看如何切换到主线程的

ObserveOnObserver类:

static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
    implements Observer<T>, Runnable {

     ...

        @Override
        public void onNext(T t) {
            // 执行过error / complete 会是true
            if (done) {
                return;
            }

            // 如果数据源类型不是异步的, 默认不是
            if (sourceMode != QueueDisposable.ASYNC) {
                // 将上游push过来的数据 加入 queue里
                queue.offer(t);
            }
            //开始进入对应Workder线程,在线程里 将queue里的t 取出 发送给下游Observer
            schedule();
        }

        ...


         void schedule() {
            if (getAndIncrement() == 0) {
                //将ObserveOnObserver(实现了Runnable)加入worker,这里是重点2
                worker.schedule(this);
            }
        }
        
        ...

    }

在schedule调用了worker.schedule(this)方法,我们可以思考,在这边将Runnable加入了worker中,那么一定会调用其实现的run方法,而run方法里就是主线程了

我们去看内部调用方法:

Scheduler类:

 public Disposable schedule(@NonNull Runnable run) {
            return schedule(run, 0L, TimeUnit.NANOSECONDS);
        }

//抽象方法,所以我们要找到实现它的类
public abstract Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit);

这里的schedule是AndroidSchedulers.mainThread(),那么我们去这个类去看看,

//AndroidSchedulers类:
   public static Scheduler mainThread() {
        return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
}

//RxAndroidPlugins类
  public static Scheduler onMainThreadScheduler(Scheduler scheduler) {
        if (scheduler == null) {
            throw new NullPointerException("scheduler == null");
        }
        //其实这里还是一个hook机制,默认这边的onMainThreadHandler为null
        Function<Scheduler, Scheduler> f = onMainThreadHandler;
        if (f == null) {
            //直接返回传入的scheduler
            return scheduler;
        }
        return apply(f, scheduler);
    }

通过上方的代码分析,那么直接看MAIN_THREAD是如何生成的,继续看代码:

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

//RxAndroidPlugins类:
public static Scheduler initMainThreadScheduler(Callable<Scheduler> scheduler) {
        if (scheduler == null) {
            throw new NullPointerException("scheduler == null");
        }
        //又是一个hook机制,onInitMainThreadHandler默认为null
        Function<Callable<Scheduler>, Scheduler> f = onInitMainThreadHandler;
        if (f == null) {
            //返回这个方法
            return callRequireNonNull(scheduler);
        }
        return applyRequireNonNull(f, scheduler);
    }

//RxAndroidPlugins类:
static Scheduler callRequireNonNull(Callable<Scheduler> s) {
        try {
            //这边调用了call方法,拿到scheduler,并且返回
            Scheduler scheduler = s.call();
            if (scheduler == null) {
                throw new NullPointerException("Scheduler Callable returned null");
            }
            return scheduler;
        } catch (Throwable ex) {
            throw Exceptions.propagate(ex);
        }
    }

通过 Scheduler scheduler = s.call();这个方法得知,最上面的call代码返回的值,就是这个scheduler,就是这个MainHolder.DEFAULT。
AndroidSchedulers类:

 private static final class MainHolder {
       //最终的scheduler方法
        static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));
    }

可以看出来,这里传入了一个主线程的Handler

我们去看看HandlerScheduler类方法

HandlerScheduler类:

final class HandlerScheduler extends Scheduler {

    //主线程的handler
    private final Handler handler;

    HandlerScheduler(Handler handler) {
        this.handler = handler;
    }

    ...

     @Override
    public Worker createWorker() {
        //这里不就是重点1,调用的方法吗,所以worker就是HandlerWorker
        return new HandlerWorker(handler);
    }


}

从上面的代码,我们终于找到了worker的实现类了,我们找到了worker类,那么我们就去找重点2的那个方法,看实现的schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit)的具体实现代码。

去看HandlerWorker的实现方法

 //HandlerWorker类
 public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
            
            ...
            hook机制,其实就是获取到run
            run = RxJavaPlugins.onSchedule(run);

            //一个代理类,其实还是一个实现的Runnable的类
            ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);

            //获取到message,将scheduled赋值到callBack里
            Message message = Message.obtain(handler, scheduled);
            message.obj = this; // Used as token for batch disposal of this worker's runnables.

            //handler发送消息,delay是0
            handler.sendMessageDelayed(message, unit.toMillis(delay));

            ...
 
            return scheduled;
        }


//Message类
public static Message obtain(Handler h, Runnable callback) {
        Message m = obtain();
        m.target = h;
        //给message的callback赋值上面的Runnable
        m.callback = callback;

        return m;
    }  

上面的代码,获取到一个message,然后直接通过handler发送消息,这个handler之前已经说过,是一个主线程Looper.getMainLooper()的handler。其实之后,就是handler机制了的,最终主线程的Looper循环,获取到message信息,最终会调用handler的dispatchMessage方法。

public void dispatchMessage(@NonNull Message msg) {
    //这里已经是主线程了
        if (msg.callback != null) {
            //之前将其callback赋值了,所以会执行此地方的代码
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            //这里不就是我们正常情况下,自定义handler处理代码的地方吗
            handleMessage(msg);
        }
    }


     private static void handleCallback(Message message) {
        //从这里可以看到,调用了callback的run方法
        message.callback.run();
    }

这里可以自己敲代码验证一下,例子如下:

 case R.id.btn10:
 //button点击后,发送一个消息
                Handler handler = new Handler(Looper.getMainLooper());
                myRunnable runnable = new myRunnable();
                Message message = Message.obtain(handler, runnable);
                handler.sendMessage(message);
                break;

...
 class myRunnable implements java.lang.Runnable {

        @Override
        public void run() {
            Log.d(TAG, "这里执行了" + Thread.currentThread());
        }
    }

执行结果为:这里执行了Thread[main,5,main]

从上面的代码知道,就是传入的message的callback执行了run方法,callback就是代理类ScheduledRunnable,那我们看下他的run方法

private static final class ScheduledRunnable implements Runnable, Disposable {

 @Override
        public void run() {
            try {
                //这里已经是主线程了
                //这里的delegate就是重点2传入的Runnable,也就是ObserveOnObserver
                delegate.run();
            } catch (Throwable t) {
                RxJavaPlugins.onError(t);
            }
        }
 }

从上面的代码中,可知,通过消息机制,已经进入了主线程,这个时候,再调用ObserveOnObserver的run方法,我们继续看代码

  static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
    implements Observer<T>, Runnable {

       ...
       @Override
        public void run() {
            //从这里开始,这个方法已经是在Workder对应的线程里执行的了
            //默认是false
            if (outputFused) {
                drainFused();
            } else {
                drainNormal();
            }
        }
        ...


 void drainNormal() {
            int missed = 1;

            final SimpleQueue<T> q = queue;
            final Observer<? super T> a = actual;

            for (;;) {
                // 如果已经 终止 或者queue空,则跳出函数,
                if (checkTerminated(done, q.isEmpty(), a)) {
                    return;
                }

                for (;;) {
                    boolean d = done;
                    T v;

                    try {
                        //从queue里取出一个值
                        v = q.poll();
                    } catch (Throwable ex) {
                        //异常处理 并跳出函数
                        Exceptions.throwIfFatal(ex);
                        s.dispose();
                        q.clear();
                        a.onError(ex);
                        worker.dispose();
                        return;
                    }
                    ...
                    
                    //发送给下游了
                    a.onNext(v);
                }

                ...
            }
        }
    }

从上面,就看出来了,在下游的onNext方法里,已经变成了主线程了。

总结:

  1. ObserveOnObserver实现了Observer和Runnable接口。
  2. 在onNext()里,先不切换线程,将数据加入队列queue。然后开始切换线程,在另一线程中,从queue里取出数据,push给下游Observer
  3. 所以observeOn()影响的是其下游的代码,且多次调用仍然生效。
  4. 因为其切换线程代码是在Observer里onXXX()做的,这是一个主动的push行为(影响下游)。
  5. 关于多次调用生效问题,observeOn()是一个主动的行为,每次切换线程后会立刻发送数据,在OnXXX()方法里执行代码,所以会生效多次.
  6. 最终能切换到主线程,是通过消息机制,主线程的looper一直循环获取MessageQueue的message消息,然后调用他的callback.run方法

这样整个切换到主线程的流程已经分析完了。本篇文章结束。

参考文章:https://www.jianshu.com/p/6ef45f8ee79d

你可能感兴趣的:(Android)