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>
对象,也就是发布者。 - 当调用
Observable
的subscribe()
方法,看一下方法声明,是一个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()
方法,就调用了 observer
的 onNext()
方法,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 的线程切换原理