揭秘 RxJava 基础核心操作模块:从源码剖析其使用原理
一、引言
在现代的软件开发领域,响应式编程正逐渐成为一种主流的编程范式。它能够以一种简洁、高效且灵活的方式处理异步数据流,尤其适用于处理复杂的异步操作和事件驱动的场景。RxJava 作为 Java 平台上响应式编程的优秀实现,为开发者提供了丰富的操作符和工具,极大地简化了异步编程的复杂度。
本博客将深入探讨 RxJava 基础核心操作模块的使用原理,通过对源码的详细分析,帮助读者理解 RxJava 是如何实现各种操作符的,以及这些操作符背后的设计思想和工作机制。我们将从最基本的概念入手,逐步深入到每个核心操作模块的内部实现,让读者对 RxJava 有一个全面而深入的认识。
二、RxJava 基础概念
2.1 响应式编程概述
响应式编程是一种面向数据流和变化传播的编程范式。它的核心思想是将数据的变化看作是一种流,通过对这些流进行操作和转换,实现数据的处理和响应。在响应式编程中,数据的变化会自动触发相应的操作,从而实现高效的异步处理和事件驱动。
例如,在一个图形用户界面(GUI)应用中,用户的鼠标点击、键盘输入等事件都可以看作是数据流。通过响应式编程,我们可以将这些事件流进行处理和转换,实现界面的交互和更新。
2.2 RxJava 的基本概念
2.2.1 Observable 和 Observer
- Observable:可观察对象,它是数据流的生产者,负责产生并发送数据。一个
Observable对象可以发出零个或多个数据项,并且可以在数据发送完成后发出一个完成信号或者一个错误信号。
import io.reactivex.Observable;
// 创建一个 Observable 对象,发出三个整数数据
Observable<Integer> observable = Observable.just(1, 2, 3);
在上述代码中,Observable.just(1, 2, 3) 创建了一个 Observable 对象,它会依次发出整数 1、2 和 3。
- Observer:观察者,它是数据流的消费者,负责接收并处理
Observable发出的数据。一个Observer对象需要实现onNext()、onError()和onComplete()三个方法,分别用于处理接收到的数据、处理错误和处理完成信号。
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
// 创建一个 Observer 对象
Observer<Integer> observer = new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
// 当观察者订阅 Observable 时调用
System.out.println("onSubscribe");
}
@Override
public void onNext(Integer value) {
// 当接收到 Observable 发出的数据时调用
System.out.println("onNext: " + value);
}
@Override
public void onError(Throwable e) {
// 当 Observable 发出错误信号时调用
System.out.println("onError: " + e.getMessage());
}
@Override
public void onComplete() {
// 当 Observable 发出完成信号时调用
System.out.println("onComplete");
}
};
在上述代码中,我们创建了一个 Observer 对象,并重写了 onSubscribe()、onNext()、onError() 和 onComplete() 方法。
- 订阅关系:通过
subscribe()方法可以将Observable和Observer建立订阅关系,从而使Observer能够接收到Observable发出的数据。
// 建立 Observable 和 Observer 的订阅关系
observable.subscribe(observer);
在上述代码中,observable.subscribe(observer) 建立了 observable 和 observer 的订阅关系,observer 会开始接收 observable 发出的数据。
2.2.2 Disposable
Disposable 是一个用于管理订阅关系的接口,它提供了 dispose() 方法用于取消订阅。当调用 dispose() 方法后,Observer 将不再接收 Observable 发出的数据。
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
// 创建一个 Observable 对象
Observable<Integer> observable = Observable.just(1, 2, 3);
// 创建一个 Observer 对象
Observer<Integer> observer = new Observer<Integer>() {
private Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
this.disposable = d;
// 可以在这里决定是否取消订阅
// disposable.dispose();
}
@Override
public void onNext(Integer value) {
if (value == 2) {
// 当接收到数据 2 时,取消订阅
disposable.dispose();
}
System.out.println("onNext: " + value);
}
@Override
public void onError(Throwable e) {
System.out.println("onError: " + e.getMessage());
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
};
// 建立订阅关系
observable.subscribe(observer);
在上述代码中,我们在 onSubscribe() 方法中保存了 Disposable 对象,并在 onNext() 方法中根据条件取消了订阅。
2.2.3 Scheduler
Scheduler 是 RxJava 中用于控制线程调度的工具。它可以指定 Observable 发出数据的线程和 Observer 接收数据的线程。RxJava 提供了多种内置的 Scheduler,如 Schedulers.io() 用于 I/O 操作、Schedulers.computation() 用于计算密集型操作等。
import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers;
// 创建一个 Observable 对象
Observable<Integer> observable = Observable.just(1, 2, 3);
// 指定 Observable 发出数据的线程为 I/O 线程
observable.subscribeOn(Schedulers.io())
// 指定 Observer 接收数据的线程为计算线程
.observeOn(Schedulers.computation())
.subscribe(System.out::println);
在上述代码中,subscribeOn(Schedulers.io()) 指定了 Observable 发出数据的线程为 I/O 线程,observeOn(Schedulers.computation()) 指定了 Observer 接收数据的线程为计算线程。
三、创建操作符
3.1 create() 操作符
3.1.1 基本使用
create() 操作符是最基本的创建 Observable 的方法,它允许开发者手动控制 Observable 的数据发射过程。通过 ObservableOnSubscribe 接口,我们可以定义 Observable 如何发出数据、错误和完成信号。
import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
// 创建一个 Observable 对象,使用 create() 操作符
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
// 发出数据 1
emitter.onNext(1);
// 发出数据 2
emitter.onNext(2);
// 发出数据 3
emitter.onNext(3);
// 发出完成信号
emitter.onComplete();
}
});
// 创建一个 Observer 对象
Observer<Integer> observer = new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("onSubscribe");
}
@Override
public void onNext(Integer value) {
System.out.println("onNext: " + value);
}
@Override
public void onError(Throwable e) {
System.out.println("onError: " + e.getMessage());
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
};
// 建立订阅关系
observable.subscribe(observer);
在上述代码中,我们使用 create() 操作符创建了一个 Observable 对象,并在 subscribe() 方法中手动控制数据的发射。
3.1.2 源码分析
create() 方法的源码如下:
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
// 检查 source 是否为 null
ObjectHelper.requireNonNull(source, "source is null");
// 创建一个 ObservableCreate 对象,将 source 作为参数传入
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
在上述代码中,create() 方法首先检查传入的 ObservableOnSubscribe 对象是否为 null,然后创建了一个 ObservableCreate 对象,并将 source 作为参数传入。最后,调用 RxJavaPlugins.onAssembly() 方法对 ObservableCreate 对象进行一些全局的组装操作。
ObservableCreate 类的源码如下:
public final class ObservableCreate<T> extends Observable<T> {
final ObservableOnSubscribe<T> source;
public ObservableCreate(ObservableOnSubscribe<T> source) {
// 保存传入的 ObservableOnSubscribe 对象
this.source = source;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
// 创建一个 CreateEmitter 对象,用于发射数据
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
// 调用观察者的 onSubscribe() 方法
observer.onSubscribe(parent);
try {
// 调用 ObservableOnSubscribe 的 subscribe() 方法,开始发射数据
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
// 如果发生异常,调用 CreateEmitter 的 onError() 方法
parent.onError(ex);
}
}
static final class CreateEmitter<T>
extends AtomicReference<Disposable>
implements ObservableEmitter<T>, Disposable {
private static final long serialVersionUID = -3434801548987643227L;
final Observer<? super T> observer;
CreateEmitter(Observer<? super T> observer) {
// 保存传入的 Observer 对象
this.observer = observer;
}
@Override
public void onNext(T t) {
if (t == null) {
// 如果数据为 null,调用 onError() 方法
onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
return;
}
if (!isDisposed()) {
// 如果没有取消订阅,调用观察者的 onNext() 方法
observer.onNext(t);
}
}
@Override
public void onError(Throwable t) {
if (!tryOnError(t)) {
// 如果无法处理错误,打印错误信息
RxJavaPlugins.onError(t);
}
}
@Override
public boolean tryOnError(Throwable t) {
if (t == null) {
// 如果错误为 null,创建一个新的 NullPointerException
t = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources."));
}
if (!isDisposed()) {
try {
// 如果没有取消订阅,调用观察者的 onError() 方法
observer.onError(t);
} finally {
// 取消订阅
dispose();
}
return true;
}
return false;
}
@Override
public void onComplete() {
if (!isDisposed()) {
try {
// 如果没有取消订阅,调用观察者的 onComplete() 方法
observer.onComplete();
} finally {
// 取消订阅
dispose();
}
}
}
@Override
public void setDisposable(Disposable d) {
// 设置 Disposable 对象
DisposableHelper.set(this, d);
}
@Override
public void setCancellable(Cancellable c) {
// 设置 Cancellable 对象
setDisposable(new CancellableDisposable(c));
}
@Override
public ObservableEmitter<T> serialize() {
// 返回一个序列化的 ObservableEmitter 对象
return new SerializedEmitter<T>(this);
}
@Override
public void dispose() {
// 取消订阅
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
// 判断是否已经取消订阅
return DisposableHelper.isDisposed(get());
}
}
}
在 ObservableCreate 类中,subscribeActual() 方法是核心方法,它会在 Observable 被订阅时调用。在该方法中,首先创建了一个 CreateEmitter 对象,然后调用观察者的 onSubscribe() 方法,接着调用 ObservableOnSubscribe 的 subscribe() 方法开始发射数据。
CreateEmitter 类实现了 ObservableEmitter 接口,用于发射数据、错误和完成信号。它会根据订阅状态和数据的有效性来决定是否调用观察者的相应方法。
3.2 just() 操作符
3.2.1 基本使用
just() 操作符用于创建一个 Observable 对象,它会依次发出传入的参数作为数据项。
import io.reactivex.Observable;
// 创建一个 Observable 对象,使用 just() 操作符
Observable<Integer> observable = Observable.just(1, 2, 3);
// 订阅 Observable 并打印接收到的数据
observable.subscribe(System.out::println);
在上述代码中,Observable.just(1, 2, 3) 创建了一个 Observable 对象,它会依次发出整数 1、2 和 3。
3.2.2 源码分析
just() 方法有多个重载版本,这里以传入多个参数的版本为例进行分析:
public static <T> Observable<T> just(T item1, T item2, T item3) {
// 检查传入的参数是否为 null
ObjectHelper.requireNonNull(item1, "The first item is null");
ObjectHelper.requireNonNull(item2, "The second item is null");
ObjectHelper.requireNonNull(item3, "The third item is null");
// 创建一个 ObservableJust 对象,将参数作为数组传入
return RxJavaPlugins.onAssembly(new ObservableJust<T>(new Object[] { item1, item2, item3 }));
}
在上述代码中,just() 方法首先检查传入的参数是否为 null,然后创建了一个 ObservableJust 对象,并将参数作为数组传入。最后,调用 RxJavaPlugins.onAssembly() 方法对 ObservableJust 对象进行一些全局的组装操作。
ObservableJust 类的源码如下:
public final class ObservableJust<T> extends Observable<T> implements ScalarCallable<T> {
private final T value;
public ObservableJust(final T value) {
// 保存传入的值
this.value = value;
}
@Override
protected void subscribeActual(Observer<? super T> s) {
// 创建一个 ScalarDisposable 对象,用于发射数据
ScalarDisposable<T> sd = new ScalarDisposable<T>(s, value);
// 调用观察者的 onSubscribe() 方法
s.onSubscribe(sd);
// 尝试发射数据
sd.run();
}
@Override
public T call() {
// 返回保存的值
return value;
}
static final class ScalarDisposable<T>
extends AtomicInteger
implements Disposable, Runnable {
private static final long serialVersionUID = 3880992722410194083L;
final Observer<? super T> observer;
final T value;
ScalarDisposable(Observer<? super T> observer, T value) {
// 保存观察者和值
this.observer = observer;
this.value = value;
}
@Override
public void run() {
if (get() == 0 && compareAndSet(0, 1)) {
try {
// 调用观察者的 onNext() 方法
observer.onNext(value);
if (get() == 1) {
// 调用观察者的 onComplete() 方法
lazySet(2);
observer.onComplete();
}
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
if (get() == 1) {
// 如果发生异常,调用观察者的 onError() 方法
lazySet(2);
observer.onError(ex);
} else {
// 打印错误信息
RxJavaPlugins.onError(ex);
}
}
}
}
@Override
public void dispose() {
// 取消订阅
set(2);
}
@Override
public boolean isDisposed() {
// 判断是否已经取消订阅
return get() == 2;
}
}
}
在 ObservableJust 类中,subscribeActual() 方法是核心方法,它会在 Observable 被订阅时调用。在该方法中,首先创建了一个 ScalarDisposable 对象,然后调用观察者的 onSubscribe() 方法,接着调用 ScalarDisposable 的 run() 方法开始发射数据。
ScalarDisposable 类实现了 Disposable 和 Runnable 接口,用于发射数据和处理取消订阅操作。在 run() 方法中,它会调用观察者的 onNext() 方法发射数据,然后调用 onComplete() 方法表示数据发射完成。
3.3 fromArray() 操作符
3.3.1 基本使用
fromArray() 操作符用于创建一个 Observable 对象,它会依次发出数组中的元素作为数据项。
import io.reactivex.Observable;
// 创建一个数组
Integer[] array = {1, 2, 3};
// 创建一个 Observable 对象,使用 fromArray() 操作符
Observable<Integer> observable = Observable.fromArray(array);
// 订阅 Observable 并打印接收到的数据
observable.subscribe(System.out::println);
在上述代码中,Observable.fromArray(array) 创建了一个 Observable 对象,它会依次发出数组 array 中的元素。
3.3.2 源码分析
fromArray() 方法的源码如下:
public static <T> Observable<T> fromArray(T... items) {
// 检查传入的数组是否为 null
ObjectHelper.requireNonNull(items, "items is null");
if (items.length == 0) {
// 如果数组长度为 0,返回一个空的 Observable 对象
return empty();
} else if (items.length == 1) {
// 如果数组长度为 1,返回一个只发出一个元素的 Observable 对象
return just(items[0]);
}
// 创建一个 ObservableFromArray 对象,将数组作为参数传入
return RxJavaPlugins.onAssembly(new ObservableFromArray<T>(items));
}
在上述代码中,fromArray() 方法首先检查传入的数组是否为 null,然后根据数组的长度进行不同的处理。如果数组长度为 0,返回一个空的 Observable 对象;如果数组长度为 1,返回一个只发出一个元素的 Observable 对象;否则,创建一个 ObservableFromArray 对象,并将数组作为参数传入。最后,调用 RxJavaPlugins.onAssembly() 方法对 ObservableFromArray 对象进行一些全局的组装操作。
ObservableFromArray 类的源码如下:
public final class ObservableFromArray<T> extends Observable<T> {
final T[] array;
public ObservableFromArray(T[] array) {
// 保存传入的数组
this.array = array;
}
@Override
protected void subscribeActual(Observer<? super T> s) {
// 创建一个 FromArrayDisposable 对象,用于发射数据
FromArrayDisposable<T> d = new FromArrayDisposable<T>(s, array);
// 调用观察者的 onSubscribe() 方法
s.onSubscribe(d);
if (d.fusionMode) {
return;
}
// 发射数据
d.run();
}
static final class FromArrayDisposable<T>
extends BasicQueueDisposable<T> {
private static final long serialVersionUID = 3601286194409310724L;
final Observer<? super T> actual;
final T[] array;
int index;
boolean fusionMode;
FromArrayDisposable(Observer<? super T> actual, T[] array) {
// 保存观察者和数组
this.actual = actual;
this.array = array;
}
@Override
public int requestFusion(int mode) {
if ((mode & SYNC) != 0) {
// 如果支持同步融合模式,设置融合模式标志
fusionMode = true;
return SYNC;
}
return 0;
}
@Nullable
@Override
public T poll() throws Exception {
int i = index;
T[] a = array;
if (i != a.length) {
// 从数组中取出元素
index = i + 1;
return ObjectHelper.requireNonNull(a[i], "The array element is null");
}
return null;
}
@Override
public boolean isEmpty() {
// 判断数组是否已经遍历完
return index == array.length;
}
@Override
public void clear() {
// 清空数组索引
index = array.length;
}
@Override
public void dispose() {
// 取消订阅
index = array.length;
}
@Override
public boolean isDisposed() {
// 判断是否已经取消订阅
return index == array.length;
}
void run() {
T[] a = array;
int n = a.length;
for (int i = 0; i < n && !isDisposed(); i++) {
T value = a[i];
if (value == null) {
// 如果元素为 null,调用观察者的 onError() 方法
actual.onError(new NullPointerException("The element at index " + i + " is null"));
return;
}
// 调用观察者的 onNext() 方法
actual.onNext(value);
}
if (!isDisposed()) {
// 调用观察者的 onComplete() 方法
actual.onComplete();
}
}
}
}
在 ObservableFromArray 类中,subscribeActual() 方法是核心方法,它会在 Observable 被订阅时调用。在该方法中,首先创建了一个 FromArrayDisposable 对象,然后调用观察者的 onSubscribe() 方法,接着根据融合模式的设置决定是否发射数据。
FromArrayDisposable 类实现了 BasicQueueDisposable 接口,用于发射数据和处理取消订阅操作。在 run() 方法中,它会遍历数组,依次调用观察者的 onNext() 方法发射数据,最后调用 onComplete() 方法表示数据发射完成。
3.4 interval() 操作符
3.4.1 基本使用
interval() 操作符用于创建一个 Observable 对象,它会按照指定的时间间隔依次发出从 0 开始的递增整数。
import io.reactivex.Observable;
import java.util.concurrent.TimeUnit;
// 创建一个 Observable 对象,使用 interval() 操作符,每隔 1 秒发出一个整数
Observable<Long> observable = Observable.interval(1, TimeUnit.SECONDS);
// 订阅 Observable 并打印接收到的数据
observable.subscribe(System.out::println);
// 为了让程序持续运行一段时间,休眠 5 秒
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
在上述代码中,Observable.interval(1, TimeUnit.SECONDS) 创建了一个 Observable 对象,它会每隔 1 秒发出一个从 0 开始的递增整数。
3.4.2 源码分析
interval() 方法的源码如下:
public static Observable<Long> interval(long initialDelay, long period, TimeUnit unit, Scheduler scheduler) {
// 检查传入的参数是否为 null
ObjectHelper.requireNonNull(unit, "unit is null");
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
// 创建一个 ObservableInterval 对象,将参数传入
return RxJavaPlugins.onAssembly(new ObservableInterval(initialDelay, period, unit, scheduler));
}
在上述代码中,interval() 方法首先检查传入的参数是否为 null,然后创建了一个 ObservableInterval 对象,并将参数传入。最后,调用 RxJavaPlugins.onAssembly() 方法对 ObservableInterval 对象进行一些全局的组装操作。
ObservableInterval 类的源码如下:
public final class ObservableInterval extends Observable<Long> {
final long initialDelay;
final long period;
final TimeUnit unit;
final Scheduler scheduler;
public ObservableInterval(long initialDelay, long period, TimeUnit unit, Scheduler scheduler) {
// 保存传入的参数
this.initialDelay = initialDelay;
this.period = period;
this.unit = unit;
this.scheduler = scheduler;
}
@Override
protected void subscribeActual(Observer<? super Long> observer) {
// 创建一个 IntervalObserver 对象,用于处理数据发射
IntervalObserver is = new IntervalObserver(observer);
// 调用观察者的 onSubscribe() 方法
observer.onSubscribe(is);
// 创建一个 Scheduler.Worker 对象,用于调度任务
Scheduler.Worker w = scheduler.createWorker();
// 设置 Disposable 对象
is.setResource(w);
// 调度任务,按照指定的时间间隔执行
w.schedulePeriodically(is, initialDelay, period, unit);
}
static final class IntervalObserver
extends AtomicReference<Disposable>
implements Disposable, Runnable {
private static final long serialVersionUID = 346773832286157679L;
final Observer<? super Long> actual;
long count;
IntervalObserver(Observer<? super Long> actual) {
// 保存观察者
this.actual = actual;
}
@Override
public void run() {
if (get() != DisposableHelper.DISPOSED) {
// 如果没有取消订阅,调用观察者的 onNext() 方法
actual.onNext(count++);
}
}
@Override
public void dispose() {
// 取消订阅
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
// 判断是否已经取消订阅
return get() == DisposableHelper.DISPOSED;
}
void setResource(Disposable d) {
// 设置 Disposable 对象
DisposableHelper.setOnce(this, d);
}
}
}
在 ObservableInterval 类中,subscribeActual() 方法是核心方法,它会在 Observable 被订阅时调用。在该方法中,首先创建了一个 IntervalObserver 对象,然后调用观察者的 onSubscribe() 方法,接着创建了一个 Scheduler.Worker 对象,用于调度任务。最后,调用 Scheduler.Worker 的 schedulePeriodically() 方法,按照指定的时间间隔执行 IntervalObserver 的 run() 方法。
IntervalObserver 类实现了 Disposable 和 Runnable 接口,用于处理数据发射和取消订阅操作。在 run() 方法中,它会调用观察者的 onNext() 方法发射数据,并递增计数器。
四、变换操作符
4.1 map() 操作符
4.1.1 基本使用
map() 操作符用于对 Observable 发出的每一个数据项进行转换,将其转换为另一种类型的数据项。
import io.reactivex.Observable;
// 创建一个 Observable 对象,发出整数 1、2、3
Observable<Integer> observable = Observable.just(1, 2, 3);
// 使用 map() 操作符将每个整数乘以 2
Observable<Integer> mappedObservable = observable.map(new Function<Integer, Integer>() {
@Override
public Integer apply(Integer value) throws Exception {
return value * 2;
}
});
// 订阅转换后的 Observable 并打印接收到的数据
mappedObservable.subscribe(System.out::println);
在上述代码中,map() 操作符将 Observable 发出的每个整数乘以 2,然后发出转换后的整数。
4.1.2 源码分析
map() 方法的源码如下:
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
// 检查传入的 mapper 是否为 null
ObjectHelper.requireNonNull(mapper, "mapper is null");
// 创建一个 ObservableMap 对象,将当前 Observable 和 mapper 作为参数传入
return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}
在上述代码中,map() 方法首先检查传入的 Function 对象是否为 null,然后创建了一个 ObservableMap 对象,并将当前 Observable 和 mapper 作为参数传入。最后,调用 RxJavaPlugins.onAssembly() 方法对 ObservableMap 对象进行一些全局的组装操作。
ObservableMap 类的源码如下:
public final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
final Function<? super T, ? extends U> function;
public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
// 调用父类的构造方法,保存上游 Observable
super(source);
// 保存传入的 mapper
this.function = function;
}
@Override
public void subscribeActual(Observer<? super U> t) {
// 创建一个 MapObserver 对象,将下游观察者和 mapper 作为参数传入
source.subscribe(new MapObserver<T, U>(t, function));
}
static final class MapObserver<T, U> extends BasicFuseableObserver<T, U> {
final Function<? super T, ? extends U> mapper;
MapObserver(Observer<? super U> actual, Function<? super T, ? extends U> mapper) {
// 调用父类的构造方法,保存下游观察者
super(actual);
// 保存传入的 mapper
this.mapper = mapper;
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
// 如果处于融合模式,直接传递数据
actual.onNext(null);
return;
}
U v;
try {
// 调用 mapper 的 apply() 方法进行数据转换
v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
} catch (Throwable ex) {
// 如果发生异常,调用父类的 onError() 方法
fail(ex);
return;
}
// 调用下游观察者的 onNext() 方法
actual.onNext(v);
}
@Override
public int requestFusion(int mode) {
// 尝试进行融合模式
return transitiveBoundaryFusion(mode);
}
@Nullable
@Override
public U poll() throws Exception {
// 从上游获取数据并进行转换
T t = qs.poll();
return t != null ? ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.") : null;
}
}
}
在 ObservableMap 类中,subscribeActual() 方法是核心方法,它会在 Observable 被订阅时调用。在该方法中,创建了一个 MapObserver 对象,并将其作为下游观察者传递给上游 Observable 的 subscribe() 方法。
MapObserver 类实现了 BasicFuseableObserver 接口,用于处理数据转换和融合模式。在 onNext() 方法中,它会调用 mapper 的 apply() 方法对数据进行转换,然后将转换后的数据传递给下游观察者。
4.2 flatMap() 操作符
4.2.1 基本使用
flatMap() 操作符用于将 Observable 发出的每个数据项转换为一个 Observable,然后将这些 Observable 发出的数据合并成一个新的 Observable。
import io.reactivex.Observable;
// 创建一个 Observable 对象,发出整数 1、2、3
Observable<Integer> observable = Observable.just(1, 2, 3);
// 使用 flatMap() 操作符将每个整数转换为一个 Observable,发出该整数的平方和立方
Observable<Integer> flatMappedObservable = observable.flatMap(new Function<Integer, ObservableSource<Integer>>() {
@Override
public ObservableSource<Integer> apply(Integer value) throws Exception {
return Observable.just(value * value, value * value * value);
}
});
// 订阅转换后的 Observable 并打印接收到的数据
flatMappedObservable.subscribe(System.out::println);
在上述代码中,flatMap() 操作符将 Observable 发出的每个整数转换为一个 Observable,该 Observable 发出该整数的平方和立方,然后将这些 Observable 发出的数据合并成一个新的 Observable。
4.2.2 源码分析
flatMap() 方法的源码如下:
public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) {
// 检查传入的 mapper 是否为 null
ObjectHelper.requireNonNull(mapper, "mapper is null");
// 创建一个 ObservableFlatMap 对象,将当前 Observable 和 mapper 作为参数传入
return flatMap(mapper, false);
}
public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper, boolean delayErrors) {
// 检查传入的 mapper 是否为 null
ObjectHelper.requireNonNull(mapper, "mapper is null");
// 创建一个 ObservableFlatMap 对象,将当前 Observable、mapper 和 delayErrors 作为参数传入
return RxJavaPlugins.onAssembly(new ObservableFlatMap<T, R>(this, mapper, delayErrors, Integer.MAX_VALUE));
}
4.2.2 源码分析
flatMap() 方法的源码如下:
public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) {
// 检查传入的 mapper 是否为 null
ObjectHelper.requireNonNull(mapper, "mapper is null");
// 创建一个 ObservableFlatMap对象,将当前 Observable 和 mapper 作为参数传入
return flatMap(mapper, false);
}
public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper, boolean delayErrors) {
// 检查传入的 mapper 是否为 null
ObjectHelper.requireNonNull(mapper, "mapper is null");
// 创建一个 ObservableFlatMap 对象,将当前 Observable、mapper 和 delayErrors 作为参数传入
return RxJavaPlugins.onAssembly(new ObservableFlatMap<T, R>(this, mapper, delayErrors, Integer.MAX_VALUE));
}
在上述代码中,flatMap() 方法首先对传入的 mapper 函数进行非空校验,确保转换逻辑的有效性。然后通过调用重载的 flatMap() 方法,创建 ObservableFlatMap 实例,并将上游 Observable、转换函数 mapper、是否延迟错误处理的标志 delayErrors 以及最大并发数(这里设置为 Integer.MAX_VALUE)传入。
ObservableFlatMap 类的核心代码如下:
public final class ObservableFlatMap<T, U> extends AbstractObservableWithUpstream<T, U> {
final Function<? super T, ? extends ObservableSource<? extends U>> mapper;
final boolean delayErrors;
final int maxConcurrency;
public ObservableFlatMap(ObservableSource<T> source, Function<? super T, ? extends ObservableSource<? extends U>> mapper,
boolean delayErrors, int maxConcurrency) {
super(source);
this.mapper = mapper;
this.delayErrors = delayErrors;
this.maxConcurrency = maxConcurrency;
}
@Override
public void subscribeActual(Observer<? super U> observer) {
// 创建一个 MergeObserver 实例,用于处理合并逻辑
if (getClass() == ObservableFlatMap.class) {
source.subscribe(new MergeObserver<T, U>(observer, mapper, delayErrors, maxConcurrency));
} else {
// 其他情况的处理,这里暂不展开
source.subscribe(new BlockingOperatorMergeSubscriber<T, U>(observer, mapper, delayErrors, maxConcurrency));
}
}
static final class MergeObserver<T, U> extends BasicFuseableObserver<T, U>
implements Observer<T>, Disposable, InnerObserver<U>, Runnable, QueueDisposable<U> {
private static final long serialVersionUID = -7720116335840841829L;
final Observer<? super U> actual;
final Function<? super T, ? extends ObservableSource<? extends U>> mapper;
final boolean delayErrors;
final int maxConcurrency;
// 用于存储上游发送的数据转换后的 Observable 对应的 Disposable
final List<Disposable> sources = new ArrayList<>();
// 用于存储上游发送的数据转换后的 Observable 发出的数据
final Queue<U> queue = new SpscLinkedArrayQueue<>(QueueDisposable.bufferSize());
// 用于控制并发数量
int wip;
// 记录错误信息
Throwable error;
// 标记是否完成
boolean done;
// 用于取消订阅
Disposable s;
MergeObserver(Observer<? super U> actual, Function<? super T, ? extends ObservableSource<? extends U>> mapper,
boolean delayErrors, int maxConcurrency) {
this.actual = actual;
this.mapper = mapper;
this.delayErrors = delayErrors;
this.maxConcurrency = maxConcurrency;
}
@Override
public void onSubscribe(Disposable s) {
if (DisposableHelper.validate(this.s, s)) {
this.s = s;
actual.onSubscribe(this);
}
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
// 如果处于融合模式,直接处理数据
queue.offer(null);
return;
}
try {
// 使用 mapper 函数将上游数据转换为新的 Observable
ObservableSource<? extends U> source = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper returned a null ObservableSource");
// 订阅转换后的 Observable
source.subscribe(this);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
s.dispose();
onError(ex);
}
}
@Override
public void onError(Throwable t) {
if (done) {
RxJavaPlugins.onError(t);
return;
}
error = t;
if (delayErrors) {
// 如果是延迟错误处理,只有在所有上游 Observable 都完成后才通知下游
drain();
} else {
s.dispose();
actual.onError(t);
}
}
@Override
public void onComplete() {
done = true;
drain();
}
@Override
public void onSubscribe(Disposable s) {
if (DisposableHelper.add(sources, s)) {
// 如果添加成功,判断是否需要增加并发处理
if (sources.size() == 1 && wip == 0) {
s.dispose();
actual.onError(new CompositeException(sources));
return;
}
if (maxConcurrency != Integer.MAX_VALUE && sources.size() == maxConcurrency) {
// 如果达到最大并发数,取消多余的订阅
for (Disposable d : sources) {
if (d != s) {
d.dispose();
}
}
sources.clear();
}
} else {
s.dispose();
}
}
@Override
public void onNext(U t) {
// 将转换后的 Observable 发出的数据放入队列
queue.offer(t);
drain();
}
@Override
public void onError(Throwable t) {
if (delayErrors) {
// 如果是延迟错误处理,将错误信息暂存
error = ExceptionHelper.addThrowable(error, t);
} else {
for (Disposable d : sources) {
d.dispose();
}
sources.clear();
actual.onError(t);
}
}
@Override
public void onComplete() {
if (sources.remove(this)) {
// 移除当前完成的 Observable 对应的 Disposable
drain();
}
}
void drain() {
if (wip != 0 ||!QueueDisposableHelper.openSubscription(this, queue)) {
return;
}
int missed = 1;
final Observer<? super U> a = actual;
final List<Disposable> sources = this.sources;
final Queue<U> q = queue;
for (;;) {
for (; ; ) {
boolean d = done;
U v;
try {
v = q.poll();
} catch (Throwable ex) {
for (Disposable s : sources) {
s.dispose();
}
sources.clear();
q.clear();
a.onError(ex);
return;
}
boolean empty = v == null;
if (checkTerminated(d, empty, a)) {
return;
}
if (empty) {
break;
}
a.onNext(v);
}
missed = wip - missed;
if (missed == 0) {
break;
}
wip = 0;
}
}
boolean checkTerminated(boolean d, boolean empty, Observer<? super U> a) {
if (d) {
if (delayErrors) {
if (error != null) {
a.onError(error);
} else {
a.onComplete();
}
} else if (empty) {
Throwable e = error;
if (e != null) {
a.onError(e);
} else {
a.onComplete();
}
}
return true;
}
return false;
}
@Override
public void dispose() {
// 取消所有相关的订阅
s.dispose();
for (Disposable d : sources) {
d.dispose();
}
sources.clear();
queue.clear();
}
@Override
public boolean isDisposed() {
return s.isDisposed();
}
@Override
public void run() {
drain();
}
@Override
public int requestFusion(int mode) {
return transitiveBoundaryFusion(mode);
}
@Nullable
@Override
public U poll() throws Exception {
return queue.poll();
}
@Override
public boolean isEmpty() {
return queue.isEmpty();
}
@Override
public void clear() {
queue.clear();
}
}
}
在 ObservableFlatMap 类中,subscribeActual 方法会根据不同情况创建 MergeObserver 或其他类型的观察者。MergeObserver 类是实现 flatMap 逻辑的核心。
在 onNext 方法中,它将上游 Observable 发出的数据通过 mapper 函数转换为新的 Observable,并订阅该 Observable。当转换后的 Observable 发出数据时,onNext 方法会将数据放入 queue 队列中,并调用 drain 方法处理数据。
drain 方法是数据处理和合并的关键。它从队列中取出数据,并将其发送给下游 Observer。同时,它还负责处理错误和完成信号,根据 delayErrors 的设置决定何时通知下游 Observer 错误信息。如果所有上游 Observable 都已完成且没有错误,drain 方法会通知下游 Observer 数据发送完成。
MergeObserver 还实现了 QueueDisposable 接口,用于支持融合模式(fusion mode),在某些情况下可以提高数据处理的效率,减少数据在队列中的传递开销 。整个 flatMap 操作符通过这些复杂的逻辑,实现了将上游 Observable 发出的数据转换为多个 Observable,并将它们发出的数据合并成一个新的 Observable 的功能。
4.3 concatMap() 操作符
4.3.1 基本使用
concatMap() 操作符与 flatMap() 类似,也是将 Observable 发出的每个数据项转换为一个 Observable,但不同的是,concatMap() 会按照数据项发出的顺序,依次将转换后的 Observable 进行合并,前一个 Observable 发送完成后,才会开始订阅并接收下一个 Observable 发出的数据。
import io.reactivex.Observable;
// 创建一个 Observable 对象,发出整数 1、2、3
Observable<Integer> observable = Observable.just(1, 2, 3);
// 使用 concatMap() 操作符将每个整数转换为一个 Observable,发出该整数的平方和立方
Observable<Integer> concatMappedObservable = observable.concatMap(new io.reactivex.functions.Function<Integer, io.reactivex.ObservableSource<Integer>>() {
@Override
public io.reactivex.ObservableSource<Integer> apply(Integer value) throws Exception {
return Observable.just(value * value, value * value * value);
}
});
// 订阅转换后的 Observable 并打印接收到的数据
concatMappedObservable.subscribe(System.out::println);
在上述代码中,concatMap() 操作符先将整数 1 转换为 Observable 并发出其平方和立方,等这个 Observable 发送完成后,再对整数 2 进行同样操作,以此类推。
4.3.2 源码分析
concatMap() 方法在 Observable 类中定义如下:
public final <R> Observable<R> concatMap(Function<? super T,? extends ObservableSource<? extends R>> mapper) {
// 检查传入的 mapper 是否为 null
ObjectHelper.requireNonNull(mapper, "mapper is null");
// 创建一个 ObservableConcatMap 对象,将当前 Observable 和 mapper 作为参数传入
return RxJavaPlugins.onAssembly(new ObservableConcatMap<T, R>(this, mapper));
}
这里首先对 mapper 进行非空校验,然后创建 ObservableConcatMap 实例,将上游 Observable 和转换函数 mapper 传入,同时通过 RxJavaPlugins.onAssembly() 方法进行一些全局的组装操作。
ObservableConcatMap 类继承自 AbstractObservableWithUpstream,其核心代码如下:
public final class ObservableConcatMap<T, R> extends AbstractObservableWithUpstream<T, R> {
final Function<? super T,? extends ObservableSource<? extends R>> mapper;
public ObservableConcatMap(ObservableSource<T> source, Function<? super T,? extends ObservableSource<? extends R>> mapper) {
super(source);
this.mapper = mapper;
}
@Override
public void subscribeActual(Observer<? super R> s) {
// 创建一个 ConcatMapObserver 实例,用于处理合并逻辑
source.subscribe(new ConcatMapObserver<T, R>(s, mapper));
}
static final class ConcatMapObserver<T, R> extends BasicFuseableObserver<T, R>
implements Observer<T>, Disposable, InnerObserver<R>, Runnable {
private static final long serialVersionUID = -4480924777014457855L;
final Observer<? super R> actual;
final Function<? super T,? extends ObservableSource<? extends R>> mapper;
// 用于存储上游发送的数据转换后的 Observable 对应的 Disposable
final ArrayList<Disposable> sources = new ArrayList<>();
// 记录当前正在处理的 Observable 的索引
int index;
// 用于控制并发处理,类似于一个信号量
int wip;
// 记录错误信息
Throwable error;
// 标记是否完成
boolean done;
// 用于取消订阅
Disposable s;
ConcatMapObserver(Observer<? super R> actual, Function<? super T,? extends ObservableSource<? extends R>> mapper) {
this.actual = actual;
this.mapper = mapper;
}
@Override
public void onSubscribe(Disposable s) {
if (DisposableHelper.validate(this.s, s)) {
this.s = s;
actual.onSubscribe(this);
}
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
// 如果处于融合模式,直接处理数据
actual.onNext(null);
return;
}
try {
// 使用 mapper 函数将上游数据转换为新的 Observable
ObservableSource<? extends R> source = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper returned a null ObservableSource");
// 创建一个 InnerConcatObserver 来订阅转换后的 Observable
source.subscribe(new InnerConcatObserver<>(this));
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
s.dispose();
onError(ex);
}
}
@Override
public void onError(Throwable t) {
if (done) {
RxJavaPlugins.onError(t);
return;
}
error = t;
done = true;
drain();
}
@Override
public void onComplete() {
done = true;
drain();
}
@Override
public void onSubscribe(Disposable s) {
if (DisposableHelper.add(sources, s)) {
// 如果添加成功,判断是否需要开始处理
if (sources.size() == 1 && wip == 0) {
s.dispose();
actual.onError(new CompositeException(sources));
return;
}
} else {
s.dispose();
}
}
@Override
public void onNext(R t) {
actual.onNext(t);
}
@Override
public void onError(Throwable t) {
error = ExceptionHelper.addThrowable(error, t);
done = true;
drain();
}
@Override
public void onComplete() {
if (DisposableHelper.remove(sources, this)) {
drain();
}
}
void drain() {
if (wip != 0 || sources.isEmpty()) {
return;
}
int missed = 1;
final Observer<? super R> a = actual;
final ArrayList<Disposable> sources = this.sources;
for (;;) {
if (checkTerminated(done, a)) {
return;
}
while (index < sources.size()) {
Disposable d = sources.get(index);
if (!d.isDisposed()) {
// 开始订阅当前的 Observable
((InnerConcatObserver<R>)d).subscribeInner();
index++;
return;
}
index++;
}
index = 0;
missed = wip - missed;
if (missed == 0) {
break;
}
wip = 0;
}
}
boolean checkTerminated(boolean d, Observer<? super R> a) {
if (d) {
Throwable e = error;
if (e != null) {
a.onError(e);
} else {
a.onComplete();
}
return true;
}
return false;
}
@Override
public void dispose() {
s.dispose();
for (Disposable d : sources) {
d.dispose();
}
sources.clear();
}
@Override
public boolean isDisposed() {
return s.isDisposed();
}
@Override
public void run() {
drain();
}
@Override
public int requestFusion(int mode) {
return transitiveBoundaryFusion(mode);
}
@Nullable
@Override
public R poll() throws Exception {
return null;
}
static final class InnerConcatObserver<R> extends AtomicReference<Disposable>
implements Disposable, InnerObserver<R> {
private static final long serialVersionUID = -3074621840686372182L;
final ConcatMapObserver<?, R> parent;
InnerConcatObserver(ConcatMapObserver<?, R> parent) {
this.parent = parent;
}
@Override
public void onSubscribe(Disposable s) {
if (DisposableHelper.setOnce(this, s)) {
parent.sources.add(this);
if (parent.sources.size() == 1 && parent.wip == 0) {
s.dispose();
parent.actual.onError(new CompositeException(parent.sources));
}
} else {
s.dispose();
}
}
@Override
public void onNext(R t) {
parent.actual.onNext(t);
}
@Override
public void onError(Throwable t) {
parent.error = ExceptionHelper.addThrowable(parent.error, t);
parent.done = true;
parent.drain();
}
@Override
public void onComplete() {
if (DisposableHelper.remove(parent.sources, this)) {
parent.drain();
}
}
@Override
public void dispose() {
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
void subscribeInner() {
get().dispose();
get().subscribe(this);
}
}
}
}
在 ObservableConcatMap 类中,subscribeActual 方法创建 ConcatMapObserver 实例来处理订阅逻辑。ConcatMapObserver 类实现了多个接口,其中 onNext 方法会将上游数据通过 mapper 转换为新的 Observable,并创建 InnerConcatObserver 来订阅该 Observable。
drain 方法是实现按顺序合并的关键。它会从 sources 列表中依次取出 Disposable,并订阅对应的 Observable。只有当前 Observable 发送完成(onComplete 被调用),才会继续处理下一个 Observable。如果在处理过程中出现错误(onError 被调用),则会立即停止并将错误传递给下游 Observer。
通过这种机制,concatMap() 操作符确保了转换后的 Observable 按照上游数据发出的顺序依次进行合并,从而实现了有序的数据处理和传递 ,相比 flatMap() 更适合对数据顺序有严格要求的场景。
4.4 buffer() 操作符
4.4.1 基本使用
buffer() 操作符用于将 Observable 发出的数据收集到指定大小的缓冲区中,当缓冲区满了或者达到一定的时间间隔后,将缓冲区作为一个数据项发出。
import io.reactivex.Observable;
import java.util.List;
// 创建一个 Observable 对象,每隔 1 秒发出一个整数
Observable<Long> observable = Observable.interval(1, java.util.concurrent.TimeUnit.SECONDS);
// 使用 buffer() 操作符,将每 3 个数据收集到一个缓冲区
observable.buffer(3)
.subscribe(new io.reactivex.Observer<List<Long>>() {
@Override
public void onSubscribe(io.reactivex.disposables.Disposable d) {
System.out.println("开始订阅");
}
@Override
public void onNext(List<Long> buffer) {
System.out.println("接收到缓冲区数据: " + buffer);
}
@Override
public void onError(Throwable e) {
System.out.println("发生错误: " + e.getMessage());
}
@Override
public void onComplete() {
System.out.println("数据发送完成");
}
});
// 为了让程序持续运行一段时间,休眠 10 秒
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
在上述代码中,buffer(3) 使得 Observable 每发出 3 个数据,就将这 3 个数据组成一个 List 发送出来。
4.4.2 源码分析
buffer() 方法在 Observable 类中有多个重载版本,这里分析最常用的按数量收集的版本:
public final Observable<List<T>> buffer(int count) {
// 检查 count 是否合法(大于 0)
ObjectHelper.verifyPositive(count, "count");
// 创建一个 ObservableBufferCount 对象,将当前 Observable 和 count 作为参数传入
return RxJavaPlugins.onAssembly(new ObservableBufferCount<T>(this, count));
}
这里先对 count 进行合法性校验,确保其大于 0,然后创建 ObservableBufferCount 实例,将上游 Observable 和缓冲区大小 count 传入,并通过 RxJavaPlugins.onAssembly() 进行全局组装。
ObservableBufferCount 类继承自 AbstractObservableWithUpstream,其核心代码如下:
public final class ObservableBufferCount<T> extends AbstractObservableWithUpstream<T, List<T>> {
final int count;
public ObservableBufferCount(ObservableSource<T> source, int count) {
super(source);
this.count = count;
}
@Override
public void subscribeActual(Observer<? super List<T>> s) {
// 创建一个 BufferObserver 实例,用于处理缓冲区逻辑
source.subscribe(new BufferObserver<T>(s, count));
}
static final class BufferObserver<T> extends BasicFuseableObserver<T, List<T>>
implements Disposable {
private static final long serialVersionUID = -2834885649622276437L;
final Observer<? super List<T>> actual;
final int count;
// 用于存储缓冲区数据
final ArrayList<T> list;
// 用于取消订阅
Disposable s;
BufferObserver(Observer<? super List<T>> actual, int count) {
this.actual = actual;
this.count = count;
this.list = new ArrayList<>();
}
@Override
public void onSubscribe(Disposable s) {
if (DisposableHelper.validate(this.s, s)) {
this.s = s;
actual.onSubscribe(this);
}
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
// 如果处于融合模式,直接处理数据
actual.onNext(null);
return;
}
list.add(t);
if (list.size() == count) {
// 如果缓冲区满了,将缓冲区数据发送给下游,并清空缓冲区
ArrayList<T> local = list;
list.clear();
actual.onNext(local);
}
}
@Override
public void onError(Throwable t) {
if (done) {
RxJavaPlugins.onError(t);
return;
}
done = true;
list.clear();
actual.onError(t);
}
@Override
public void onComplete() {
if (done) {
return;
}
done = true;
if (!list.isEmpty()) {
// 如果缓冲区还有剩余数据,将其发送给下游
actual.onNext(list);
}
actual.onComplete();
}
@Override
public void dispose() {
s.dispose();
list.clear();
}
@Override
public boolean isDisposed() {
return s.isDisposed();
}
@Override
public int requestFusion(int mode) {
return transitiveBoundaryFusion(mode);
}
@Nullable
@Override
public List<T> poll() throws Exception {
if (sourceMode == SYNC) {
if (list.isEmpty()) {
return null;
}
ArrayList<T> local = list;
list.clear();
return local;
}
return null;
}
}
}
在 ObservableBufferCount 类中,subscribeActual 方法创建 BufferObserver 实例来处理订阅逻辑。BufferObserver 类的 onNext 方法会将上游数据添加到 list 缓冲区中,当缓冲区大小达到 count 时,将缓冲区数据组成 List 发送给下游 Observer,并清空缓冲区。
在 onComplete 方法中,如果在 Observable 完成时缓冲区还有剩余数据,也会将这些数据组成 List 发送给下游 Observer,确保所有数据都能被处理。通过这种方式,buffer() 操作符实现了将连续的数据收集到缓冲区并按批次发出的功能,方便对数据进行批量处理 。
五、过滤操作符
5.1 filter() 操作符
5.1.1 基本使用
filter()操作符用于从Observable发出的数据中筛选出符合特定条件的数据项,只有满足条件的数据才会被发送给下游的Observer。
import io.reactivex.Observable;
// 创建一个Observable对象,发出整数1到10
Observable<Integer> observable = Observable.range(1, 10);
// 使用filter()操作符筛选出偶数
Observable<Integer> filteredObservable = observable.filter(new io.reactivex.functions.Predicate<Integer>() {
@Override
public boolean test(Integer value) throws Exception {
return value % 2 == 0;
}
});
// 订阅过滤后的Observable并打印接收到的数据
filteredObservable.subscribe(System.out::println);
在上述代码中,filter()操作符通过Predicate函数定义筛选条件,只允许偶数通过并发送给下游Observer。
5.1.2 源码分析
filter()方法在Observable类中定义如下:
public final Observable<T> filter(Predicate<? super T> predicate) {
// 检查传入的Predicate是否为null
ObjectHelper.requireNonNull(predicate, "predicate is null");
// 创建一个ObservableFilter对象,将当前Observable和Predicate作为参数传入
return RxJavaPlugins.onAssembly(new ObservableFilter<T>(this, predicate));
}
该方法首先对Predicate进行非空校验,然后创建ObservableFilter实例,并通过RxJavaPlugins.onAssembly()方法进行全局组装操作。
ObservableFilter类继承自AbstractObservableWithUpstream,其核心代码如下:
public final class ObservableFilter<T> extends AbstractObservableWithUpstream<T, T> {
final Predicate<? super T> predicate;
public ObservableFilter(ObservableSource<T> source, Predicate<? super T> predicate) {
super(source);
this.predicate = predicate;
}
@Override
public void subscribeActual(Observer<? super T> s) {
// 创建一个FilterObserver实例,用于处理过滤逻辑
source.subscribe(new FilterObserver<T>(s, predicate));
}
static final class FilterObserver<T> extends BasicFuseableObserver<T, T> {
private static final long serialVersionUID = -3009044653058046526L;
final Predicate<? super T> predicate;
FilterObserver(Observer<? super T> actual, Predicate<? super T> predicate) {
super(actual);
this.predicate = predicate;
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
// 如果处于融合模式,直接处理数据
actual.onNext(null);
return;
}
try {
if (predicate.test(t)) {
// 如果数据满足条件,将其发送给下游Observer
actual.onNext(t);
}
} catch (Throwable e) {
// 如果在判断条件时发生异常,通知下游Observer错误
fail(e);
}
}
@Override
public int requestFusion(int mode) {
return transitiveBoundaryFusion(mode);
}
@Nullable
@Override
public T poll() throws Exception {
T v;
for (;;) {
v = qs.poll();
if (v == null) {
return null;
}
if (predicate.test(v)) {
// 在融合模式下,从队列中取出满足条件的数据
return v;
}
}
}
}
}
在ObservableFilter类中,subscribeActual方法创建FilterObserver实例来处理订阅逻辑。FilterObserver类的onNext方法在接收到上游Observable的数据后,调用Predicate的test方法判断数据是否满足条件。如果满足条件,则将数据发送给下游Observer;如果不满足条件,则直接忽略该数据。在融合模式下,poll方法会从队列中不断取出数据进行条件判断,直到找到满足条件的数据返回给下游,从而实现高效的数据过滤。
5.2 distinct() 操作符
5.2.1 基本使用
distinct()操作符用于过滤掉Observable发出的重复数据项,只允许第一次出现的数据通过并发送给下游Observer。
import io.reactivex.Observable;
// 创建一个Observable对象,发出数据1, 2, 2, 3, 1, 4
Observable<Integer> observable = Observable.just(1, 2, 2, 3, 1, 4);
// 使用distinct()操作符过滤重复数据
Observable<Integer> distinctObservable = observable.distinct();
// 订阅过滤后的Observable并打印接收到的数据
distinctObservable.subscribe(System.out::println);
在上述代码中,distinct()操作符会将重复的数据2和1过滤掉,最终下游Observer只会收到1, 2, 3, 4。
5.2.2 源码分析
distinct()方法在Observable类中定义如下:
public final Observable<T> distinct() {
// 创建一个ObservableDistinct对象,将当前Observable作为参数传入
return RxJavaPlugins.onAssembly(new ObservableDistinct<T>(this));
}
该方法直接创建ObservableDistinct实例,并通过RxJavaPlugins.onAssembly()方法进行全局组装。
ObservableDistinct类继承自AbstractObservableWithUpstream,其核心代码如下:
public final class ObservableDistinct<T> extends AbstractObservableWithUpstream<T, T> {
public ObservableDistinct(ObservableSource<T> source) {
super(source);
}
@Override
public void subscribeActual(Observer<? super T> s) {
// 创建一个DistinctObserver实例,用于处理去重逻辑
source.subscribe(new DistinctObserver<T>(s));
}
static final class DistinctObserver<T> extends BasicFuseableObserver<T, T> {
private static final long serialVersionUID = -5580183291188949823L;
// 使用HashSet存储已经出现过的数据
final Set<T> set;
DistinctObserver(Observer<? super T> actual) {
super(actual);
// 初始化HashSet
this.set = new HashSet<T>();
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
// 如果处于融合模式,直接处理数据
actual.onNext(null);
return;
}
if (set.add(t)) {
// 如果数据在Set中不存在(即第一次出现),将其发送给下游Observer
actual.onNext(t);
}
}
@Override
public int requestFusion(int mode) {
return transitiveBoundaryFusion(mode);
}
@Nullable
@Override
public T poll() throws Exception {
T v;
for (;;) {
v = qs.poll();
if (v == null) {
return null;
}
if (set.add(v)) {
// 在融合模式下,从队列中取出不重复的数据
return v;
}
}
}
}
}
在ObservableDistinct类中,subscribeActual方法创建DistinctObserver实例来处理订阅逻辑。DistinctObserver类中通过一个HashSet来存储已经出现过的数据。在onNext方法中,每接收到上游Observable的数据,就尝试将其添加到HashSet中。由于HashSet不允许重复元素,当add方法返回true时,说明该数据是第一次出现,此时将数据发送给下游Observer;如果add方法返回false,则说明数据已经出现过,直接忽略该数据。在融合模式下,poll方法同样利用HashSet的特性,从队列中筛选出不重复的数据返回给下游,实现数据去重的功能。
5.3 take() 操作符
5.3.1 基本使用
take()操作符用于从Observable发出的数据中只取前n个数据项发送给下游Observer,在获取到指定数量的数据后,Observable会自动发出完成信号。
import io.reactivex.Observable;
// 创建一个Observable对象,发出整数1到10
Observable<Integer> observable = Observable.range(1, 10);
//使用take()操作符只取前5个数据
Observable<Integer> takeObservable = observable.take(5);
//订阅处理后的Observable并打印接收到的数据
takeObservable.subscribe(System.out::println);
在上述代码中,take(5)使得下游Observer只会接收到前5个数据,即1, 2, 3, 4, 5,之后Observable会发出完成信号。
5.3.2 源码分析
take()方法在Observable类中定义如下:
public final Observable<T> take(long count) {
// 检查count是否合法(大于等于0)
if (count < 0) {
throw new IllegalArgumentException("count < 0: " + count);
}
// 如果count为0,直接返回一个空的Observable
if (count == 0L) {
return RxJavaPlugins.onAssembly(Observable.empty());
}
// 创建一个ObservableTake对象,将当前Observable和count作为参数传入
return RxJavaPlugins.onAssembly(new ObservableTake<T>(this, count));
}
该方法首先对count进行合法性校验,确保其大于等于0。如果count为0,则返回一个空的Observable;否则创建ObservableTake实例,并通过RxJavaPlugins.onAssembly()方法进行全局组装。
ObservableTake类继承自AbstractObservableWithUpstream,其核心代码如下:
public final class ObservableTake<T> extends AbstractObservableWithUpstream<T, T> {
final long count;
public ObservableTake(ObservableSource<T> source, long count) {
super(source);
this.count = count;
}
@Override
public void subscribeActual(Observer<? super T> s) {
// 根据count的不同情况创建不同的Observer
if (count == Long.MAX_VALUE) {
source.subscribe(s);
} else {
source.subscribe(new TakeObserver<T>(s, count));
}
}
static final class TakeObserver<T> extends BasicFuseableObserver<T, T> {
private static final long serialVersionUID = -9064447276924681822L;
long remaining;
TakeObserver(Observer<? super T> actual, long count) {
super(actual);
this.remaining = count;
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
// 如果处于融合模式,直接处理数据
actual.onNext(null);
return;
}
long r = remaining;
if (r == 1) {
// 如果只剩下一个数据,将其发送给下游Observer并发出完成信号
done = true;
actual.onNext(t);
actual.onComplete();
} else {
// 将数据发送给下游Observer,并减少剩余数据数量
actual.onNext(t);
remaining = r - 1;
}
}
@Override
public int requestFusion(int mode) {
return transitiveBoundaryFusion(mode);
}
@Nullable
@Override
public T poll() throws Exception {
if (sourceMode == SYNC) {
long r = remaining;
if (r == 1) {
// 在融合模式下,当只剩下一个数据时,取出数据并发出完成信号
done = true;
T v = qs.poll();
actual.onComplete();
return v;
} else if (r > 0) {
// 在融合模式下,取出数据并减少剩余数量
remaining = r - 1;
return qs.poll();
}
return null;
}
return null;
}
}
}
在ObservableTake类中,subscribeActual方法根据count的值决定如何订阅上游Observable。如果count为Long.MAX_VALUE,则直接将下游Observer订阅到上游Observable;否则创建TakeObserver实例。TakeObserver类的onNext方法在接收到上游数据后,会检查剩余需要获取的数据数量remaining。当remaining为1时,将数据发送给下游Observer并发出完成信号;否则将数据发送给下游Observer并减少remaining的值。在融合模式下,poll方法同样根据remaining的值来决定是否继续从队列中取出数据以及何时发出完成信号,从而实现按数量截取数据的功能。
六、组合操作符
6.1 merge() 操作符
6.1.1 基本使用
merge()操作符用于将多个Observable合并为一个Observable,合并后的Observable会按照数据项发出的顺序,将所有Observable发出的数据依次发送给下游Observer。当所有的Observable都完成时,合并后的Observable才会发出完成信号。
import io.reactivex.Observable;
// 创建两个Observable对象
Observable<Integer> observable1 = Observable.just(1, 2, 3);
Observable<Integer> observable2 = Observable.just(4, 5, 6);
// 使用merge()操作符合并两个Observable
Observable<Integer> mergedObservable = Observable.merge(observable1, observable2);
// 订阅合并后的Observable并打印接收到的数据
mergedObservable.subscribe(System.out::println);
在上述代码中,merge()操作符将observable1和observable2合并,下游Observer会依次收到1, 2, 3, 4, 5, 6。
6.1.2 源码分析
merge()方法有多个重载版本,以下是接收多个Observable参数的版本源码:
@SafeVarargs
public static <T> Observable<T> merge(ObservableSource<? extends T>... sources) {
// 检查传入的Observable数组是否为null
ObjectHelper.requireNonNull(sources, "sources is null");
// 如果只有一个Observable,直接返回该Observable
if (sources.length == 1) {
@SuppressWarnings("unchecked")
ObservableSource<T> s = (ObservableSource<T>)sources[0];
return RxJavaPlugins.onAssembly((Observable<T>)s);
}
// 创建一个ObservableMerge对象,将多个Observable作为参数传入
return RxJavaPlugins.onAssembly(new ObservableMerge<>(sources));
}
该方法首先对传入的Observable数组进行非空校验。如果数组只有一个元素,直接返回该元素对应的Observable;否则创建ObservableMerge实例,并通过RxJavaPlugins.onAssembly()方法进行全局组装。
ObservableMerge类继承自AbstractObservableWithUpstream,其核心代码如下:
public final class ObservableMerge<T> extends AbstractObservableWithUpstream<ObservableSource<? extends T>, T> {
final ObservableSource<? extends T>[] sources;
@SafeVarargs
public ObservableMerge(ObservableSource<? extends T>... sources) {
super(Observable.fromArray(sources));
this.sources = sources;
}
@Override
public void subscribeActual(Observer<? super T> s) {
// 创建一个MergeObserver实例,用于处理合并逻辑
MergeObserver<T> mergeObserver = new MergeObserver<>(s);
s.onSubscribe(mergeObserver);
for (ObservableSource<? extends T> source : sources) {
if (source == null) {
// 如果有Observable为null,发出错误信号
mergeObserver.onError(new NullPointerException("One of the sources is null"));
return;
}
// 订阅每个Observable,并将MergeObserver作为观察者
source.subscribe(mergeObserver);
}
}
static final class MergeObserver<T> extends BasicFuseableObserver<ObservableSource<? extends T>, T>
implements Observer<ObservableSource<? extends T>>, Disposable, InnerObserver<T>, Runnable, QueueDisposable<T> {
private static final long serialVersionUID = -7720116335840841829L;
final Observer<? super T> actual;
// 用于存储所有Observable对应的Disposable
final ArrayList<Disposable> sources = new ArrayList<>();
// 用于存储Observable发出的数据
final Queue<T> queue = new SpscLinkedArrayQueue<>(QueueDisposable.bufferSize());
// 用于控制并发处理
int wip;
// 记录错误信息
Throwable error;
// 标记是否所有Observable都已完成
boolean done;
// 用于取消订阅
Disposable s;
MergeObserver(Observer<? super T> actual) {
this.actual = actual;
}
@Override
public void onSubscribe(Disposable s) {
if
接上分析 MergeObserver 类的剩余部分以及整个 merge() 操作符的工作原理。
MergeObserver 类的完整分析
static final class MergeObserver<T> extends BasicFuseableObserver<ObservableSource<? extends T>, T>
implements Observer<ObservableSource<? extends T>>, Disposable, InnerObserver<T>, Runnable, QueueDisposable<T> {
private static final long serialVersionUID = -7720116335840841829L;
final Observer<? super T> actual;
// 用于存储所有Observable对应的Disposable
final ArrayList<Disposable> sources = new ArrayList<>();
// 用于存储Observable发出的数据
final Queue<T> queue = new SpscLinkedArrayQueue<>(QueueDisposable.bufferSize());
// 用于控制并发处理
int wip;
// 记录错误信息
Throwable error;
// 标记是否所有Observable都已完成
boolean done;
// 用于取消订阅
Disposable s;
MergeObserver(Observer<? super T> actual) {
this.actual = actual;
}
@Override
public void onSubscribe(Disposable s) {
if (DisposableHelper.validate(this.s, s)) {
this.s = s;
actual.onSubscribe(this);
}
}
@Override
public void onNext(ObservableSource<? extends T> t) {
if (done) {
return;
}
if (sourceMode != NONE) {
// 如果处于融合模式,直接处理数据
actual.onNext(null);
return;
}
try {
// 创建一个InnerObserver来订阅每个Observable
InnerObserver<T> inner = new InnerObserver<>(this);
// 存储该Observable对应的Disposable
sources.add(inner);
// 订阅当前的Observable
t.subscribe(inner);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
s.dispose();
onError(ex);
}
}
@Override
public void onError(Throwable t) {
if (done) {
RxJavaPlugins.onError(t);
return;
}
error = t;
done = true;
drain();
}
@Override
public void onComplete() {
done = true;
drain();
}
@Override
public void onSubscribe(Disposable s) {
if (DisposableHelper.add(sources, s)) {
if (sources.size() == 1 && wip == 0) {
s.dispose();
actual.onError(new CompositeException(sources));
return;
}
} else {
s.dispose();
}
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
actual.onNext(null);
return;
}
// 将接收到的数据存入队列
queue.offer(t);
drain();
}
@Override
public void onError(Throwable t) {
if (delayErrors) {
// 如果是延迟错误处理,将错误信息暂存
error = ExceptionHelper.addThrowable(error, t);
} else {
for (Disposable d : sources) {
d.dispose();
}
sources.clear();
actual.onError(t);
}
}
@Override
public void onComplete() {
if (sources.remove(this)) {
// 移除当前完成的Observable对应的Disposable
drain();
}
}
void drain() {
if (wip != 0 ||!QueueDisposableHelper.openSubscription(this, queue)) {
return;
}
int missed = 1;
final Observer<? super T> a = actual;
final List<Disposable> sources = this.sources;
final Queue<T> q = queue;
for (;;) {
for (; ; ) {
boolean d = done;
T v;
try {
v = q.poll();
} catch (Throwable ex) {
for (Disposable s : sources) {
s.dispose();
}
sources.clear();
q.clear();
a.onError(ex);
return;
}
boolean empty = v == null;
if (checkTerminated(d, empty, a)) {
return;
}
if (empty) {
break;
}
// 将队列中的数据发送给下游Observer
a.onNext(v);
}
missed = wip - missed;
if (missed == 0) {
break;
}
wip = 0;
}
}
boolean checkTerminated(boolean d, boolean empty, Observer<? super T> a) {
if (d) {
if (delayErrors) {
if (error != null) {
a.onError(error);
} else {
a.onComplete();
}
} else if (empty) {
Throwable e = error;
if (e != null) {
a.onError(e);
} else {
a.onComplete();
}
}
return true;
}
return false;
}
@Override
public void dispose() {
// 取消所有相关的订阅
s.dispose();
for (Disposable d : sources) {
d.dispose();
}
sources.clear();
queue.clear();
}
@Override
public boolean isDisposed() {
return s.isDisposed();
}
@Override
public void run() {
drain();
}
@Override
public int requestFusion(int mode) {
return transitiveBoundaryFusion(mode);
}
@Nullable
@Override
public T poll() throws Exception {
return queue.poll();
}
@Override
public boolean isEmpty() {
return queue.isEmpty();
}
@Override
public void clear() {
queue.clear();
}
}
工作流程总结
- 订阅阶段:在
subscribeActual方法中,MergeObserver会遍历传入的所有Observable,并为每个Observable创建一个InnerObserver进行订阅。同时,将这些Observable对应的Disposable存储在sources列表中。 - 数据接收阶段:当某个
Observable发出数据时,MergeObserver的onNext方法会将数据存入queue队列中,然后调用drain方法处理队列中的数据。 - 数据处理阶段:
drain方法会不断从queue队列中取出数据,并将其发送给下游的Observer。如果在处理过程中所有Observable都完成(done为true)且队列中没有数据(empty为true),则会根据是否延迟错误处理(delayErrors)来决定是发出错误信号还是完成信号。 - 错误处理阶段:如果某个
Observable发出错误信号,MergeObserver的onError方法会根据delayErrors的设置来处理错误。如果是延迟错误处理,会将错误信息暂存,直到所有Observable都完成后再统一处理;否则会立即取消所有订阅并将错误信号发送给下游Observer。 - 取消订阅阶段:当调用
dispose方法时,MergeObserver会取消所有相关Observable的订阅,并清空sources列表和queue队列。
6.2 concat() 操作符
6.2.1 基本使用
concat() 操作符与 merge() 类似,也是用于合并多个 Observable,但不同的是,concat() 会按照传入 Observable 的顺序依次订阅并发送数据,只有当前一个 Observable 完成后,才会开始订阅并接收下一个 Observable 发出的数据。
import io.reactivex.Observable;
// 创建两个Observable对象
Observable<Integer> observable1 = Observable.just(1, 2, 3);
Observable<Integer> observable2 = Observable.just(4, 5, 6);
// 使用concat()操作符合并两个Observable
Observable<Integer> concatenatedObservable = Observable.concat(observable1, observable2);
// 订阅合并后的Observable并打印接收到的数据
concatenatedObservable.subscribe(System.out::println);
在上述代码中,下游 Observer 会先收到 observable1 发出的 1, 2, 3,等 observable1 完成后,再收到 observable2 发出的 4, 5, 6。
6.2.2 源码分析
concat() 方法有多个重载版本,以下是接收多个 Observable 参数的版本源码:
@SafeVarargs
public static <T> Observable<T> concat(ObservableSource<? extends T>... sources) {
// 检查传入的Observable数组是否为null
ObjectHelper.requireNonNull(sources, "sources is null");
// 如果只有一个Observable,直接返回该Observable
if (sources.length == 1) {
@SuppressWarnings("unchecked")
ObservableSource<T> s = (ObservableSource<T>)sources[0];
return RxJavaPlugins.onAssembly((Observable<T>)s);
}
// 创建一个ObservableConcatArray对象,将多个Observable作为参数传入
return RxJavaPlugins.onAssembly(new ObservableConcatArray<>(sources));
}
该方法首先对传入的 Observable 数组进行非空校验。如果数组只有一个元素,直接返回该元素对应的 Observable;否则创建 ObservableConcatArray 实例,并通过 RxJavaPlugins.onAssembly() 方法进行全局组装。
ObservableConcatArray 类继承自 Observable,其核心代码如下:
public final class ObservableConcatArray<T> extends Observable<T> {
final ObservableSource<? extends T>[] sources;
@SafeVarargs
public ObservableConcatArray(ObservableSource<? extends T>... sources) {
this.sources = sources;
}
@Override
public void subscribeActual(Observer<? super T> observer) {
// 创建一个ConcatArrayObserver实例,用于处理合并逻辑
ConcatArrayObserver<T> parent = new ConcatArrayObserver<>(observer, sources);
observer.onSubscribe(parent);
parent.subscribeNext();
}
static final class ConcatArrayObserver<T> extends AtomicInteger implements Disposable, Observer<T> {
private static final long serialVersionUID = -8158322871608889516L;
final Observer<? super T> actual;
final ObservableSource<? extends T>[] sources;
int index;
boolean done;
Disposable s;
ConcatArrayObserver(Observer<? super T> actual, ObservableSource<? extends T>[] sources) {
this.actual = actual;
this.sources = sources;
}
@Override
public void onSubscribe(Disposable s) {
this.s = s;
}
@Override
public void onNext(T t) {
actual.onNext(t);
}
@Override
public void onError(Throwable t) {
done = true;
actual.onError(t);
}
@Override
public void onComplete() {
subscribeNext();
}
void subscribeNext() {
if (done) {
return;
}
if (getAndIncrement() != 0) {
return;
}
int n = sources.length;
for (; ; ) {
if (isDisposed()) {
return;
}
int idx = index;
if (idx == n) {
done = true;
actual.onComplete();
return;
}
ObservableSource<? extends T> source = sources[idx];
if (source == null) {
Throwable e = new NullPointerException("sources[" + idx + "] is null");
done = true;
actual.onError(e);
return;
}
source.subscribe(this);
index = idx + 1;
if (decrementAndGet() == 0) {
return;
}
}
}
@Override
public void dispose() {
s.dispose();
}
@Override
public boolean isDisposed() {
return s.isDisposed();
}
}
}
工作流程总结
- 订阅阶段:在
subscribeActual方法中,ObservableConcatArray会创建一个ConcatArrayObserver实例,并调用subscribeNext方法开始订阅第一个Observable。 - 数据接收阶段:当当前
Observable发出数据时,ConcatArrayObserver的onNext方法会将数据直接发送给下游Observer。 - 切换
Observable阶段:当当前Observable完成时,ConcatArrayObserver的onComplete方法会调用subscribeNext方法,开始订阅下一个Observable。 - 错误处理阶段:如果某个
Observable发出错误信号,ConcatArrayObserver的onError方法会将错误信号直接发送给下游Observer,并标记为完成。 - 取消订阅阶段:当调用
dispose方法时,ConcatArrayObserver会取消当前Observable的订阅。
通过以上分析,可以看出 merge() 和 concat() 操作符虽然都用于合并多个 Observable,但在处理数据的顺序和方式上有所不同,开发者可以根据具体需求选择合适的操作符。
6.3 zip() 操作符
6.3.1 基本使用
zip() 操作符用于将多个 Observable 发出的数据项按照索引位置进行配对组合,然后将组合后的数据发送给下游 Observer。当其中一个 Observable 完成且没有更多数据发出时,zip() 操作符就会停止工作并发出完成信号。
以下是一个简单的示例代码:
import io.reactivex.Observable;
import io.reactivex.functions.BiFunction;
// 创建两个 Observable 对象
Observable<Integer> observable1 = Observable.just(1, 2, 3);
Observable<String> observable2 = Observable.just("A", "B", "C");
// 使用 zip() 操作符将两个 Observable 进行配对组合
Observable<String> zippedObservable = Observable.zip(observable1, observable2, new BiFunction<Integer, String, String>() {
@Override
public String apply(Integer integer, String s) throws Exception {
return integer + s;
}
});
// 订阅组合后的 Observable 并打印接收到的数据
zippedObservable.subscribe(System.out::println);
在上述代码中,zip() 操作符将 observable1 和 observable2 发出的数据进行配对组合,最终下游 Observer 会收到 1A、2B、3C。
6.3.2 源码分析
zip() 方法有多个重载版本,这里分析接收两个 Observable 参数的版本:
public static <T1, T2, R> Observable<R> zip(
ObservableSource<? extends T1> source1, ObservableSource<? extends T2> source2,
BiFunction<? super T1, ? super T2, ? extends R> zipper) {
// 检查参数是否为 null
ObjectHelper.requireNonNull(source1, "source1 is null");
ObjectHelper.requireNonNull(source2, "source2 is null");
ObjectHelper.requireNonNull(zipper, "zipper is null");
// 创建一个 ObservableZip 对象,将两个 Observable 和组合函数作为参数传入
return RxJavaPlugins.onAssembly(new ObservableZip<>(new ObservableSource<?>[] { source1, source2 }, zipper));
}
该方法首先对传入的两个 Observable 和组合函数 zipper 进行非空校验,然后创建 ObservableZip 实例,并通过 RxJavaPlugins.onAssembly() 方法进行全局组装。
ObservableZip 类继承自 Observable,其核心代码如下:
public final class ObservableZip<T, R> extends Observable<R> {
final ObservableSource<? extends T>[] sources;
final Function<? super Object[], ? extends R> zipper;
public ObservableZip(ObservableSource<? extends T>[] sources, Function<? super Object[], ? extends R> zipper) {
this.sources = sources;
this.zipper = zipper;
}
@Override
public void subscribeActual(Observer<? super R> observer) {
// 创建一个 ZipCoordinator 实例,用于协调多个 Observable 的数据配对组合
ZipCoordinator<T, R> zc = new ZipCoordinator<>(observer, sources.length, zipper);
observer.onSubscribe(zc);
for (int i = 0; i < sources.length; i++) {
ObservableSource<? extends T> source = sources[i];
if (source == null) {
// 如果有 Observable 为 null,发出错误信号
zc.innerError(new NullPointerException("source at index " + i + " is null"), i);
return;
}
// 为每个 Observable 创建一个 ZipObserver 并进行订阅
source.subscribe(new ZipObserver<>(zc, i));
}
}
static final class ZipCoordinator<T, R> extends AtomicInteger implements Disposable {
private static final long serialVersionUID = 2983708048395377667L;
final Observer<? super R> actual;
final Function<? super Object[], ? extends R> zipper;
final ZipObserver<T>[] observers;
final Object[] row;
final AtomicInteger active;
final AtomicBoolean cancelled;
final AtomicReference<Throwable> error;
final int size;
@SuppressWarnings("unchecked")
ZipCoordinator(Observer<? super R> actual, int n, Function<? super Object[], ? extends R> zipper) {
this.actual = actual;
this.zipper = zipper;
this.size = n;
this.observers = new ZipObserver[n];
this.row = new Object[n];
this.active = new AtomicInteger(n);
this.cancelled = new AtomicBoolean();
this.error = new AtomicReference<>();
}
@Override
public void dispose() {
if (cancelled.compareAndSet(false, true)) {
for (ZipObserver<T> observer : observers) {
observer.dispose();
}
}
}
@Override
public boolean isDisposed() {
return cancelled.get();
}
void innerNext(T value, int index) {
if (!cancelled.get()) {
row[index] = value;
if (active.decrementAndGet() == 0) {
try {
// 使用组合函数将配对的数据进行组合
R v = zipper.apply(row);
if (v == null) {
throw new NullPointerException("The zipper returned a null value.");
}
// 将组合后的数据发送给下游 Observer
actual.onNext(v);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
innerError(ex, index);
return;
}
for (int i = 0; i < size; i++) {
observers[i].take();
}
active.lazySet(size);
}
}
}
void innerError(Throwable e, int index) {
if (cancelled.compareAndSet(false, true)) {
for (int i = 0; i < size; i++) {
if (i != index) {
observers[i].dispose();
}
}
error.lazySet(e);
actual.onError(e);
} else {
RxJavaPlugins.onError(e);
}
}
void innerComplete(int index) {
if (!cancelled.get()) {
observers[index].done = true;
if (checkTerminate()) {
return;
}
}
}
boolean checkTerminate() {
if (cancelled.get()) {
return true;
}
Throwable ex = error.get();
if (ex != null) {
for (ZipObserver<T> observer : observers) {
observer.dispose();
}
actual.onError(ex);
return true;
}
for (ZipObserver<T> observer : observers) {
if (!observer.done) {
return false;
}
}
actual.onComplete();
return true;
}
}
static final class ZipObserver<T> extends AtomicReference<Disposable> implements Observer<T> {
private static final long serialVersionUID = 3323743579927613702L;
final ZipCoordinator<T, ?> parent;
final int index;
final SpscLinkedArrayQueue<T> queue;
boolean done;
ZipObserver(ZipCoordinator<T, ?> parent, int index) {
this.parent = parent;
this.index = index;
this.queue = new SpscLinkedArrayQueue<>(QueueDisposable.bufferSize());
}
@Override
public void onSubscribe(Disposable s) {
DisposableHelper.setOnce(this, s);
parent.observers[index] = this;
}
@Override
public void onNext(T t) {
if (!done) {
queue.offer(t);
parent.innerNext(t, index);
}
}
@Override
public void onError(Throwable t) {
if (!done) {
done = true;
parent.innerError(t, index);
} else {
RxJavaPlugins.onError(t);
}
}
@Override
public void onComplete() {
if (!done) {
done = true;
parent.innerComplete(index);
}
}
void take() {
T v = queue.poll();
if (v != null) {
parent.innerNext(v, index);
}
}
@Override
public void dispose() {
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
}
}
工作流程总结
- 订阅阶段:在
subscribeActual方法中,ObservableZip会创建一个ZipCoordinator实例,用于协调多个Observable的数据配对组合。然后为每个Observable创建一个ZipObserver并进行订阅。 - 数据接收阶段:当某个
Observable发出数据时,对应的ZipObserver的onNext方法会将数据存入队列,并调用ZipCoordinator的innerNext方法。 - 数据组合阶段:在
ZipCoordinator的innerNext方法中,会将接收到的数据存入row数组。当所有Observable都有数据到达时(active计数器减为 0),会使用组合函数zipper将row数组中的数据进行组合,并将组合后的数据发送给下游Observer。 - 错误处理阶段:如果某个
Observable发出错误信号,对应的ZipObserver的onError方法会调用ZipCoordinator的innerError方法,该方法会取消所有Observable的订阅,并将错误信号发送给下游Observer。 - 完成处理阶段:当某个
Observable完成时,对应的ZipObserver的onComplete方法会调用ZipCoordinator的innerComplete方法。ZipCoordinator会检查是否所有Observable都已完成,如果是,则发出完成信号。 - 取消订阅阶段:当调用
dispose方法时,ZipCoordinator会取消所有Observable的订阅。
6.4 combineLatest() 操作符
6.4.1 基本使用
combineLatest() 操作符会将多个 Observable 最新发出的数据项进行组合,然后将组合后的数据发送给下游 Observer。只要其中一个 Observable 发出新的数据,就会立即与其他 Observable 最新发出的数据进行组合并发送。
以下是一个简单的示例代码:
import io.reactivex.Observable;
import io.reactivex.functions.BiFunction;
// 创建两个 Observable 对象
Observable<Integer> observable1 = Observable.just(1, 2, 3);
Observable<String> observable2 = Observable.just("A", "B", "C");
// 使用 combineLatest() 操作符将两个 Observable 进行组合
Observable<String> combinedObservable = Observable.combineLatest(observable1, observable2, new BiFunction<Integer, String, String>() {
@Override
public String apply(Integer integer, String s) throws Exception {
return integer + s;
}
});
// 订阅组合后的 Observable 并打印接收到的数据
combinedObservable.subscribe(System.out::println);
在上述代码中,combineLatest() 操作符会将 observable1 和 observable2 最新发出的数据进行组合,最终下游 Observer 会收到组合后的数据。
6.4.2 源码分析
combineLatest() 方法有多个重载版本,这里分析接收两个 Observable 参数的版本:
public static <T1, T2, R> Observable<R> combineLatest(
ObservableSource<? extends T1> source1, ObservableSource<? extends T2> source2,
BiFunction<? super T1, ? super T2, ? extends R> combiner) {
// 检查参数是否为 null
ObjectHelper.requireNonNull(source1, "source1 is null");
ObjectHelper.requireNonNull(source2, "source2 is null");
ObjectHelper.requireNonNull(combiner, "combiner is null");
// 创建一个 ObservableCombineLatest 对象,将两个 Observable 和组合函数作为参数传入
return RxJavaPlugins.onAssembly(new ObservableCombineLatest<>(new ObservableSource<?>[] { source1, source2 }, combiner));
}
该方法首先对传入的两个 Observable 和组合函数 combiner 进行非空校验,然后创建 ObservableCombineLatest 实例,并通过 RxJavaPlugins.onAssembly() 方法进行全局组装。
ObservableCombineLatest 类继承自 Observable,其核心代码如下:
public final class ObservableCombineLatest<T, R> extends Observable<R> {
final ObservableSource<? extends T>[] sources;
final Function<? super Object[], ? extends R> combiner;
public ObservableCombineLatest(ObservableSource<? extends T>[] sources, Function<? super Object[], ? extends R> combiner) {
this.sources = sources;
this.combiner = combiner;
}
@Override
public void subscribeActual(Observer<? super R> observer) {
// 创建一个 CombineLatestCoordinator 实例,用于协调多个 Observable 的数据组合
CombineLatestCoordinator<T, R> clc = new CombineLatestCoordinator<>(observer, combiner, sources.length);
observer.onSubscribe(clc);
for (int i = 0; i < sources.length; i++) {
ObservableSource<? extends T> source = sources[i];
if (source == null) {
// 如果有 Observable 为 null,发出错误信号
clc.innerError(new NullPointerException("source at index " + i + " is null"), i);
return;
}
// 为每个 Observable 创建一个 CombineLatestObserver 并进行订阅
source.subscribe(new CombineLatestObserver<>(clc, i));
}
}
static final class CombineLatestCoordinator<T, R> extends AtomicInteger implements Disposable {
private static final long serialVersionUID = -5586979301535943796L;
final Observer<? super R> actual;
final Function<? super Object[], ? extends R> combiner;
final CombineLatestObserver<T>[] observers;
final Object[] latest;
final AtomicInteger active;
final AtomicBoolean cancelled;
final AtomicReference<Throwable> error;
final int size;
@SuppressWarnings("unchecked")
CombineLatestCoordinator(Observer<? super R> actual, Function<? super Object[], ? extends R> combiner, int n) {
this.actual = actual;
this.combiner = combiner;
this.size = n;
this.observers = new CombineLatestObserver[n];
this.latest = new Object[n];
this.active = new AtomicInteger(n);
this.cancelled = new AtomicBoolean();
this.error = new AtomicReference<>();
}
@Override
public void dispose() {
if (cancelled.compareAndSet(false, true)) {
for (CombineLatestObserver<T> observer : observers) {
observer.dispose();
}
}
}
@Override
public boolean isDisposed() {
return cancelled.get();
}
void innerNext(T value, int index) {
if (!cancelled.get()) {
latest[index] = value;
if (active.get() == 0) {
try {
// 使用组合函数将最新的数据进行组合
R v = combiner.apply(latest);
if (v == null) {
throw new NullPointerException("The combiner returned a null value.");
}
// 将组合后的数据发送给下游 Observer
actual.onNext(v);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
innerError(ex, index);
return;
}
}
}
}
void innerError(Throwable e, int index) {
if (cancelled.compareAndSet(false, true)) {
for (int i = 0; i < size; i++) {
if (i != index) {
observers[i].dispose();
}
}
error.lazySet(e);
actual.onError(e);
} else {
RxJavaPlugins.onError(e);
}
}
void innerComplete(int index) {
if (!cancelled.get()) {
observers[index].done = true;
if (checkTerminate()) {
return;
}
}
}
boolean checkTerminate() {
if (cancelled.get()) {
return true;
}
Throwable ex = error.get();
if (ex != null) {
for (CombineLatestObserver<T> observer : observers) {
observer.dispose();
}
actual.onError(ex);
return true;
}
for (CombineLatestObserver<T> observer : observers) {
if (!observer.done) {
return false;
}
}
actual.onComplete();
return true;
}
}
static final class CombineLatestObserver<T> extends AtomicReference<Disposable> implements Observer<T> {
private static final long serialVersionUID = 3323743579927613702L;
final CombineLatestCoordinator<T, ?> parent;
final int index;
boolean done;
CombineLatestObserver(CombineLatestCoordinator<T, ?> parent, int index) {
this.parent = parent;
this.index = index;
}
@Override
public void onSubscribe(Disposable s) {
DisposableHelper.setOnce(this, s);
parent.observers[index] = this;
}
@Override
public void onNext(T t) {
if (!done) {
parent.innerNext(t, index);
}
}
@Override
public void onError(Throwable t) {
if (!done) {
done = true;
parent.innerError(t, index);
} else {
RxJavaPlugins.onError(t);
}
}
@Override
public void onComplete() {
if (!done) {
done = true;
parent.innerComplete(index);
}
}
@Override
public void dispose() {
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
}
}
工作流程总结
- 订阅阶段:在
subscribeActual方法中,ObservableCombineLatest会创建一个CombineLatestCoordinator实例,用于协调多个Observable的数据组合。然后为每个Observable创建一个CombineLatestObserver并进行订阅。 - 数据接收阶段:当某个
Observable发出数据时,对应的CombineLatestObserver的onNext方法会调用CombineLatestCoordinator的innerNext方法。 - 数据组合阶段:在
CombineLatestCoordinator的innerNext方法中,会将接收到的数据存入latest数组。当所有Observable都至少发出过一次数据时(active计数器为 0),会使用组合函数combiner将latest数组中的最新数据进行组合,并将组合后的数据发送给下游Observer。 - 错误处理阶段:如果某个
Observable发出错误信号,对应的CombineLatestObserver的onError方法会调用CombineLatestCoordinator的innerError方法,该方法会取消所有Observable的订阅,并将错误信号发送给下游Observer。 - 完成处理阶段:当某个
Observable完成时,对应的CombineLatestObserver的onComplete方法会调用CombineLatestCoordinator的innerComplete方法。CombineLatestCoordinator会检查是否所有Observable都已完成,如果是,则发出完成信号。 - 取消订阅阶段:当调用
dispose方法时,CombineLatestCoordinator会取消所有Observable的订阅。
通过以上分析,可以看出 zip() 和 combineLatest() 操作符虽然都用于组合多个 Observable 的数据,但在组合方式上有所不同。zip() 是按索引位置配对组合,而 combineLatest() 是将最新的数据进行组合。开发者可以根据具体需求选择合适的操作符。