第七章:RxJava 3.x 新特性与迁移指南

77 阅读5分钟

1. RxJava 3 核心变化

1.1 包结构与命名空间重构

RxJava 3 最重要的变化是包名和命名空间的改变:

// RxJava 2.x
import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers;

// RxJava 3.x
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;

主要变更点

  • 包名从 io.reactivex 改为 io.reactivex.rxjava3
  • 所有基础类都移到了 core 子包中
  • 与 RxJava 2 完全兼容,可以共存

1.2 接口与类层次优化

RxJava 3 重新设计了核心接口层次:

// RxJava 2.x
public interface ObservableSource<T> {
    void subscribe(Observer<? super T> observer);
}

// RxJava 3.x
public interface ObservableSource<T> {
    void subscribe(@NonNull Observer<? super T> observer);
}

// 新增 Null 注解支持
@NonNull
Observable<T> map(@NonNull Function<? super T, ? extends R> mapper);

主要改进

  • 全面引入 @NonNull 和 @Nullable 注解
  • 更严格的空安全约束
  • 统一了 SingleMaybeCompletable 的接口设计

2. 新操作符剖析

2.1 switchMapSingle / switchMapMaybe

// RxJava 2.x 需要额外操作
observable
    .switchMap(value -> 
        api.getData(value).toObservable()
    )
    .subscribe();

// RxJava 3.x 直接支持
observable
    .switchMapSingle(value -> api.getData(value))
    .subscribe();

源码实现

public final <R> Observable<R> switchMapSingle(
        Function<? super T, ? extends SingleSource<? extends R>> mapper) {
    return switchMapSingle(mapper, false);
}

public final <R> Observable<R> switchMapSingle(
        Function<? super T, ? extends SingleSource<? extends R>> mapper, 
        boolean delayErrors) {
    return new ObservableSwitchMapSingle<>(this, mapper, delayErrors);
}

优势

  • 减少 toObservable() 转换
  • 更简洁的代码表达
  • 内部优化了取消订阅逻辑

2.2 onErrorComplete 操作符

// RxJava 2.x 需要额外处理
observable
    .onErrorResumeNext(Observable.empty())
    .subscribe();

// RxJava 3.x 更简洁
observable
    .onErrorComplete()
    .subscribe();

// 带条件过滤
observable
    .onErrorComplete(error -> error instanceof IOException)
    .subscribe();

源码分析

public final Observable<T> onErrorComplete() {
    return onErrorComplete(Functions.alwaysTrue());
}

public final Observable<T> onErrorComplete(Predicate<? super Throwable> predicate) {
    return new ObservableOnErrorComplete<>(this, predicate);
}

static final class ObservableOnErrorComplete<T> extends AbstractObservableWithUpstream<T, T> {
    final Predicate<? super Throwable> predicate;

    @Override
    public void subscribeActual(Observer<? super T> observer) {
        source.subscribe(new OnErrorCompleteObserver<>(observer, predicate));
    }
    
    static final class OnErrorCompleteObserver<T> implements Observer<T> {
        @Override
        public void onError(Throwable t) {
            boolean complete;
            try {
                complete = predicate.test(t);
            } catch (Throwable e) {
                downstream.onError(e);
                return;
            }
            
            if (complete) {
                downstream.onComplete();
            } else {
                downstream.onError(t);
            }
        }
    }
}

2.3 fromCompletionStage (Java 8+)

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Result");

Observable.fromCompletionStage(future)
    .subscribe(
        result -> System.out.println("Result: " + result),
        error -> System.err.println("Error: " + error)
    );

使用场景

  • 与 Java 8+ 的 CompletableFuture 集成
  • 替代 Observable.fromFuture()
  • 更符合现代 Java 异步编程

3. 响应式流规范改进

3.1 背压策略优化

RxJava 3 改进了背压处理机制:

// RxJava 3 新增背压策略
Flowable.interval(1, TimeUnit.MILLISECONDS)
    .onBackpressureBuffer(
        100, 
        () -> System.out.println("Overflow!"), // 新增溢出回调
        BackpressureOverflowStrategy.DROP_OLDEST
    )
    .subscribe();

新增特性

  • onBackpressureBuffer 支持溢出回调
  • 更精细的背压策略控制
  • 与 Reactive Streams 规范更紧密集成

3.2 Processor 接口改进

RxJava 3 重构了 Processor 接口:

// RxJava 2.x
public abstract class FlowableProcessor<T> extends Flowable<T> implements Processor<T, T> {}

// RxJava 3.x
public abstract class FlowableProcessor<T> 
    extends Flowable<T> 
    implements FlowableSubscriber<T>, Processor<T, T> {}

主要改进

  • 明确区分 FlowableSubscriber 和 Processor
  • 更好的生命周期管理
  • 更强的类型安全

4. 测试功能增强

4.1 TestScheduler 改进

TestScheduler testScheduler = new TestScheduler();

Observable.interval(1, TimeUnit.SECONDS, testScheduler)
    .take(5)
    .test()
    .assertNoValues()
    .assertNotComplete();

// 快进时间
testScheduler.advanceTimeBy(3, TimeUnit.SECONDS);

// 验证结果
TestObserver<Long> testObserver = testScheduler.getTestObserver();
testObserver.assertValues(0L, 1L, 2L);
testObserver.assertNotComplete();

// 快进到结束
testScheduler.advanceTimeTo(5, TimeUnit.SECONDS);
testObserver.assertComplete();

新增功能

  • 精确控制虚拟时间
  • 直接获取关联的 TestObserver
  • 支持更复杂的时序测试

4.2 TestObserver 增强

TestObserver<Integer> testObserver = Observable.just(1, 2, 3)
    .test()
    .assertResult(1, 2, 3) // 结果断言
    .assertComplete()       // 完成断言
    .assertNoErrors();      // 无错误断言

// 获取详细状态
List<Integer> values = testObserver.values();
Throwable error = testObserver.errors().get(0);
int completions = testObserver.completions();

新增方法

  • values():获取所有接收的值
  • errors():获取错误列表
  • completions():完成事件计数
  • awaitCount():等待指定数量事件

5. 性能优化与内部改进

5.1 操作符融合优化

RxJava 3 扩展了操作符融合机制:

Observable.range(1, 1000)
    .map(i -> i * 2)
    .filter(i -> i % 3 == 0)
    .subscribe(new Observer<Integer>() {
        @Override
        public void onSubscribe(@NonNull Disposable d) {
            if (d instanceof QueueDisposable) {
                QueueDisposable<Integer> qd = (QueueDisposable<Integer>) d;
                
                // 请求融合
                int mode = qd.requestFusion(QueueDisposable.ANY);
                if (mode == QueueDisposable.SYNC) {
                    // 同步融合处理
                    while (!qd.isEmpty()) {
                        Integer v = qd.poll();
                        if (v != null) {
                            onNext(v);
                        }
                    }
                    onComplete();
                    return;
                }
            }
            // 常规处理
        }
    });

优化效果

  • 减少中间对象分配
  • 降低方法调用开销
  • 提升同步操作符性能30%+

5.2 内存占用优化

RxJava 3 对核心数据结构进行优化:

// RxJava 2.x 的 SpscLinkedArrayQueue
public class SpscLinkedArrayQueue<T> {
    final AtomicReferenceArray<Object> buffer;
    // 每个元素需要 24-32 字节
}

// RxJava 3.x 的 SpscLinkedArrayQueue
public class SpscLinkedArrayQueue<T> {
    final Object[] buffer;
    // 优化后每个元素只需 16 字节
}

优化点

  • 队列数据结构内存占用减少50%
  • 减少对象头开销
  • 优化缓存行对齐

6. 迁移指南与最佳实践

6.1 从 RxJava 2 迁移

步骤指南

  1. 更新依赖:

    dependencies {
        implementation "io.reactivex.rxjava3:rxjava:3.1.8"
        // 可选 Android 扩展
        implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
    }
    
  2. 替换包名:

    // 全局替换
    import io.reactivex. -> import io.reactivex.rxjava3.
    
  3. 处理 API 变更:

    • Flowable 背压策略默认值变化
    • Completable 方法签名更新
    • 废弃方法的替换
  4. 使用迁移工具:

    # 使用官方迁移脚本
    curl -sSL https://raw.githubusercontent.com/ReactiveX/RxJava/3.x/scripts/migrate-packages.py | python3 - 
    

6.2 兼容性设计

RxJava 3 提供与 RxJava 2 的互操作:

// RxJava 2 转 RxJava 3
io.reactivex.Observable<Integer> obs2 = io.reactivex.Observable.just(1, 2, 3);
Observable<Integer> obs3 = RxJavaInterop.toV3Observable(obs2);

// RxJava 3 转 RxJava 2
Observable<Integer> obs3 = Observable.just(4, 5, 6);
io.reactivex.Observable<Integer> obs2 = RxJavaInterop.toV2Observable(obs3);

互操作场景

  • 渐进式迁移大型项目
  • 使用尚未迁移到 RxJava 3 的库
  • 多模块项目中逐步迁移

6.3 Android 迁移注意事项

  1. 生命周期管理

    // RxJava 2 + AutoDispose
    observable.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
    
    // RxJava 3 + AutoDispose
    observable.as(AutoDispose.autoDisposable(ViewScopeProvider.from(view)))
    
  2. Proguard 配置

    # RxJava 3 规则
    -dontwarn io.reactivex.rxjava3.**
    -keep class io.reactivex.rxjava3.** { *; }
    
  3. 与 Jetpack 集成

    // 使用 RxJava 3 与 LiveData
    LiveDataReactiveStreams.fromPublisher(
        observable.toFlowable(BackpressureStrategy.LATEST)
    );
    

7. 响应式编程未来展望

7.1 协程集成

// 使用 RxJava 3 与 Kotlin 协程
val observable = Observable.fromCallable {
    withContext(Dispatchers.IO) {
        fetchData() // 挂起函数
    }
}

// 或者使用 RxJava 协程扩展
dependencies {
    implementation "io.reactivex.rxjava3:rxjava3-kotlin:3.1.8"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx3:1.8.0"
}
// 协程转 Observable
val observable = coroutineScope.rxObservable {
    val data1 = async { fetchData1() }
    val data2 = async { fetchData2() }
    emit(data1.await())
    emit(data2.await())
}

潜在优势

  • 百万级轻量级线程
  • 消除异步编程复杂性
  • 与现有 RxJava API 无缝集成

本章总结

  1. 包结构重构

    • 新包名 io.reactivex.rxjava3
    • 与 RxJava 2 兼容共存
    • 严格的空安全注解
  2. 新操作符

    • switchMapSingle/switchMapMaybe 简化转换
    • onErrorComplete 优雅处理错误
    • fromCompletionStage 集成现代 Java
  3. 背压与流规范

    • 增强的背压策略
    • 改进的 Processor 接口
    • 更好的 Reactive Streams 合规性
  4. 测试增强

    • 更强大的 TestScheduler
    • 增强的 TestObserver API
    • 完善的测试工具链
  5. 性能优化

    • 操作符融合深度优化
    • 队列内存占用减少50%
    • 同步操作性能提升30%+
  6. 迁移实践

    • 分步骤迁移指南
    • Android 特定注意事项
  7. 未来展望

    • Kotlin 协程深度集成
    • Project Loom 虚拟线程支持
    • 响应式与结构化并发融合

迁移建议:对于新项目,推荐直接使用 RxJava 3。对于现有项目,可以利用互操作工具逐步迁移。重点关注空安全改进、新操作符的使用以及性能优化点,这些都能显著提升代码质量和运行效率。