RxJava 2.x学习总结

1. 集成

// rxjava
implementation 'io.reactivex.rxjava2:rxjava:2.1.12'
// rxandroid
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

2. 使用

基本使用的代码:

    Observable
                .create(new ObservableOnSubscribe<String>() {
                    @Override
                    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                        emitter.onNext("a");
                        emitter.onNext("b");
                        emitter.onNext("c");
                        emitter.onComplete();
                    }
                })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d(TAG, "onSubscribe: ");
                    }

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

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

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

运行结果如下:

D/TestFragment: onSubscribe: 
D/TestFragment: onNext: s = a
D/TestFragment: onNext: s = b
D/TestFragment: onNext: s = c
D/TestFragment: onComplete: 

RxJava扩展了观察者模式,所以在上面的代码中,也存在发布者、订阅者、订阅事件这些概念。

  • Observable 是一个实现了 ObservableSource 接口的抽象类,它提供了一些工厂方法,中间操作符和处理异步&(or)同步数据流的能力。
  • 当调用 Observable 类的静态方法(或者说工厂方法)create() 方法,传入的参数是 ObservableOnSubscribe<String> 对象,返回的是 Observable<String> 对象,也就是发布者
  • 当调用 Observablesubscribe() 方法,看一下方法声明,是一个 final 类型的非 static 方法。这个就是订阅事件。它的调用者就是发布者,传入的参数是 Observer<String> 对象,这个传入的对象是订阅者

3. 订阅流程

看完上面的代码,可能会有一些疑问:

  • ObservableOnSubscribe 的回调方法 subscribe() 中写的 3 个 onNext() 和 1 个 onComplete() 是如何回调出去的?
  • 代码中并没有调用 onSubscribe() ,为什么它被回调了?

答案就在上面的代码里面,只不过我们还没有看代码的实现。

看一下 Observable 类的 subscribe() 方法:

@SchedulerSupport(SchedulerSupport.NONE)
    @Override
    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);
        } catch (NullPointerException e) { // NOPMD
            throw e;
        } 
    }

进入 Observable 类的 subscribeActual() 方法:

protected abstract void subscribeActual(Observer<? super T> observer);

这是一个抽象方法,还需要继续寻找具体实现它的地方,也就是说要寻找 Observable 类的子类。

发布者就是一个 Observable 对象,而它是通过 Observable.create() 方法构建的,所以看一下Observable 类的 create() 方法:

    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
        ObjectHelper.requireNonNull(source, "source is null"); // 非空校验
        return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }

进入到 RxJavaPlugins 类的 onAssembly() 方法中:

    /**
     * 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> Observable<T> onAssembly(@NonNull Observable<T> source) {
        Function<? super Observable, ? extends Observable> f = onObservableAssembly;
        if (f != null) {
            return apply(f, source);
        }
        return source;
    }

默认情况下,没有使用 hook 功能,所以 create() 方法实际上返回的是 new ObservableCreate<T>(source) ,其中参数 source 就是代码中 new 出来的 ObservableOnSubscribe 对象 。

接着看 ObservableCreate 类:

public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source; // 持有 ObservableOnSubscribe 对象的引用
    // 通过构造方法传入 ObservableOnSubscribe 对象
    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }
    // 重写了父类的 subscribeActual() 方法
    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        observer.onSubscribe(parent); // 调用观察者的 onSubscribe() 方法

        try {
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }
    // 这是 ObservableCreate 类的静态内部类,实现了 ObservableEmitter 接口
    static final class CreateEmitter<T>
            extends AtomicReference<Disposable>
            implements ObservableEmitter<T>, Disposable {


        private static final long serialVersionUID = -3434801548987643227L;
        // 持有观察者 observer 对象的引用
        final Observer<? super T> observer;
        // 通过构造方法传入 Observer 对象
        CreateEmitter(Observer<? super T> observer) {
            this.observer = observer;
        }
        // 当调用本方法时,如果当前对象没有 disposed,那么就会调用观察者 observer 的 onNext() 方法。
        @Override
        public void onNext(T t) {
            if (t == null) {
                onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
                return;
            }
            if (!isDisposed()) {
                observer.onNext(t);
            }
        }

        @Override
        public void onError(Throwable t) {
            if (!tryOnError(t)) {
                RxJavaPlugins.onError(t);
            }
        }

        @Override
        public void onComplete() {
            if (!isDisposed()) {
                try {
                    observer.onComplete();
                } finally {
                    dispose();
                }
            }
        }

    }

}

ObservableCreate 类是一个 final 类,继承于 Observable 抽象类,实现了 Observable 类的 subscribeActual() 抽象方法。

在这个 subscribeActual() 方法中,

observer.onSubscribe(parent);

这句代码调用观察者的 onSubscribe() 方法。

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

这句代码使用 CreateEmitter 封装了观察者 observer 对象。在它的内部调用 CreateEmitter 对象的 onNext() 方法,就调用了 observeronNext() 方法,onComplete() 方法也是如此。
而调用了

source.subscribe(parent);

就会回调到

@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
     emitter.onNext("a");
     emitter.onNext("b");
     emitter.onNext("c");
     emitter.onComplete();
}

不难发现,正是这个方法里的 emitter 对象的调用,最终调用了观察者的对应的方法。

4. 线程切换

RxJava 是一个实现异步操作的库。在不指定线程的情况下,RxJava 遵循的是线程不变的原则,subscribe() 方法执行的线程,就是生产事件的线程,而消费事件和生产事件在同一个线程。当需要线程切换时,可以使用 Scheduler

RxJava内置了几个Scheduler:

  • Schedulers.computation() : 用于 CPU 密集型计算;
  • Schedulers.io() :用于 I/O 操作(读写文件、读写数据库、网络信息交互等);
  • Schedulers.newThread() : 启用新线程,并在新线程执行操作;
  • Schedulers.single() : 表示单一的线程;
  • Schedulers.trampoline() : 表示不做任何线程操作;
  • AndroidSchedulers.mainThread() : 这个是由 RxAndroid 提供的,它指定的操作在 Android 主线程中运行。

线程切换的方法:

  • subscribeOn(Scheduler scheduler) : 指定生产事件的线程;
  • observeOn(Scheduler scheduler) : 指定消费事件的线程。

使用例子:

    Observable
                .create(new ObservableOnSubscribe<String>() {
                    @Override
                    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                        Log.d(TAG, "subscribe: curr thread = " + Thread.currentThread().getName());
                        emitter.onNext("a");
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d(TAG, "onSubscribe: curr thread = " + Thread.currentThread().getName());
                    }

                    @Override
                    public void onNext(String s) {
                        Log.d(TAG, "onNext: curr thread = " + Thread.currentThread().getName());
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "onError: curr thread = " + Thread.currentThread().getName());
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "onComplete: curr thread = " + Thread.currentThread().getName());
                    }
                });

运行结果:

D/TestFragment: onSubscribe: curr thread = main
D/TestFragment: subscribe: curr thread = RxCachedThreadScheduler-1
D/TestFragment: onNext: curr thread = main
D/TestFragment: onComplete: curr thread = main

可以看到上面的例子实现了后台线程获取数据,主线程显示的常用逻辑。

单单调用 subscribeOn(Scheduler scheduler)observeOn(Scheduler scheduler) 就可以实现线程切换,这两句代码有什么神奇之处?

observeOn(Scheduler scheduler)

使用例子:

            Observable
                        .create(new ObservableOnSubscribe<String>() {
                            @Override
                            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                                Log.d(TAG, "subscribe: curr thread = " + Thread.currentThread().getName());
                                emitter.onNext("a");
                                emitter.onComplete();
                            }
                        })
                        .observeOn(Schedulers.io())
                        .subscribe(new Observer<String>() {
                            @Override
                            public void onSubscribe(Disposable d) {
                            }

                            @Override
                            public void onNext(String s) {
                                Log.d(TAG, "onNext: curr thread = " + Thread.currentThread().getName());
                            }

                            @Override
                            public void onError(Throwable e) {
                            }

                            @Override
                            public void onComplete() {
                            }
                        });

运行结果:

D/TestFragment: subscribe: curr thread = main
D/TestFragment: onNext: curr thread = RxCachedThreadScheduler-1

这里简化了代码,和之前的例子并没有太大的区别。同样地,在调用了 observeOn(Schedulers.io()) 之后,实现了线程的切换。
跟进 Observable 类的 observeOn() 方法:

  @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.CUSTOM)
    public final Observable<T> observeOn(Scheduler scheduler) {
        return observeOn(scheduler, false, bufferSize()); //  后面的 2 个参数都是默认的,不要关心。
    }

继续跟进

    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.CUSTOM)
    public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
        ObjectHelper.requireNonNull(scheduler, "scheduler is null");
        ObjectHelper.verifyPositive(bufferSize, "bufferSize");
        // 在这里,此行代码实际返回的是 new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize)。
        return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
    }

看一下 ObservableObserveOn 类:

public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler; // Scheduler 对象,在这里它的值就是 Schedulers.io()。
    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;
    }
    // 和订阅流程中一样,当调用 subscribe() 方法时,实际执行到的是本方法。
    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        // 当 observeOn() 中传入的是 Schedulers.trampoline() 时,表示在不做任何线程操作,会走第一个分支,
        // 而这里传入的是 Schedulers.io(),所以不会走 if 分支。
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else { // 进入 else 分支
            // 创建出一个 IoScheduler.EventLoopWorker 对象。
            Scheduler.Worker w = scheduler.createWorker();

            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
        }
    }
}

再看 ObserveOnObserver 类:

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

        private static final long serialVersionUID = 6576896619930983584L;
        final Observer<? super T> actual;
        final Scheduler.Worker worker;
        final boolean delayError;
        final int bufferSize;

        ObserveOnObserver(Observer<? super T> actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
            this.actual = actual;
            this.worker = worker;
            this.delayError = delayError;
            this.bufferSize = bufferSize;
        }

        @Override
        public void onNext(T t) {
            if (done) {
                return;
            }

            if (sourceMode != QueueDisposable.ASYNC) {
                queue.offer(t);
            }
            schedule();
        }       

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

这个 ObserveOnObserver 类实现了 Runnable 接口和 Observer 接口,所以它的实例就是观察者对象,生产的事件会在这里被消费掉。当执行 emitter.onNext("a"); 时,就是调用了这里的 onNext() 方法。接着调用的是 shedule() 方法,在 shedule() 方法里,调用了 Scheduler.Worker 对象的 shedule() 方法,如下:

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

接着调用了 Scheduler 类中的:

public abstract Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit);

这是一个抽象方法,在这里,它的实现在 IoScheduler 类的静态内部类 EventLoopWorker 中:

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

跟进到 NewThreadWorker 类中:

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 对象,可以调用 submit()schedule() 方法执行任务。前面看到 ObserveOnObserver 类实现了 Runnable 接口,看一下它的 run() 方法:

@Override
public void run() {
    if (outputFused) {
        drainFused();
    } else {
        drainNormal(); // 调用这里,不清楚为什么
    }
}

然后

void drainNormal() {
    int missed = 1;

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

    for (;;) {
        if (checkTerminated(done, q.isEmpty(), a)) {
            return;
        }

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

            try {
                v = q.poll();
            } catch (Throwable ex) {
                Exceptions.throwIfFatal(ex);
                s.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;
        }
    }
}

drainNormal() 方法里最终调用了观察者对象的 onNext() 方法,执行线程自然就是 Schedulers.io() 指定的线程。总结一下,实现切换到工作线程使用的仍然是 java 中的线程池。

subscribeOn(Scheduler scheduler)

这里就不写例子了,直接把 observeOn(Schedulers.io()) 替换为 subscribeOn(Schedulers.io())
运行结果:

D/TestFragment: subscribe: curr thread = RxCachedThreadScheduler-1
D/TestFragment: onNext: curr thread = RxCachedThreadScheduler-1

跟进 Observable 类:

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

进入 ObservableSubscribeOn 类:

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

其中 SubscribeOnObserver 类实现了 Observer 接口,但是与 ObserveOnObserver 类不同的是,它没有实现 Runnable 接口。SubscribeTask 类实现了 Runnable 接口,在它的 run() 方法里面调用了 subscribe() 方法实现订阅事件:

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

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

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

通过 new SubscribeTask(parent) 构造的 Runnable 实例作为参数传入了 Scheduler 类的 scheduleDirect() 方法中:

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

接着

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);
     // 和 observeOn() 同样,这里的 task 会运行在 subscribeOn() 所指定的线程里。
     w.schedule(task, delay, unit);

     return task;
}

再看一下 DisposeTask 类,它封装了 SubscribeTask 对象,看一下它的 run() 方法:

 @Override
 public void run() {
     runner = Thread.currentThread();
     try {
         // SubscribeTask 对象的 run() 方法被调用了。
         decoratedRun.run();
     } finally {
         dispose();
         runner = null;
     }
 }

decoratedRun.run() 执行时,source.subscribe(parent) (订阅事件)也发生了,自然发生的线程是已经切换过的线程。

参考

给 Android 开发者的 RxJava 详解
友好 RxJava2.x 源码解析(一)基本订阅流程
友好 RxJava2.x 源码解析(二)线程切换
详解 RxJava2 的线程切换原理

猜你喜欢

转载自blog.csdn.net/willway_wang/article/details/80057192