RxJava 3 新不同 - 4

359 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

窗口抛弃

相似于groupBy, 操作符window发射的内部响应序列应该在外部序列取消的时候(例如, 只和有限的窗口集工作)依然保持接收数据项. 相似的, 当所有的窗口消费者取消的时候, 初始源也应该取消.

然而, 在2.x中, 没有任何机制强制消费内部源, 由此窗口只是简单地全部忽略掉, 这阻止了初始源的取消, 也可能导致源泄露.

有了3.x, 所有window操作符已经被修改了, 所以当它发射组时, 下游必须同步地订阅它. 否则, 窗口会被认为是"被抛弃"从而终止掉. 这种情况下, 被抛弃的窗口不能阻止初始流的取消. 如果后来的消费者依然订阅这个窗口, 触发窗口创建的数据项可能依然可用.

同步订阅意味着下面的流设置将会导致抛弃:

窗口抛弃示例

// observeOn creates a time gap between window emission
// and subscription
source.window(10, 5)
.observeOn(Schedulers.computation())
.flatMap(g -> g)

// subscribeOn creates a time gap too
source.window(1, TimeUnit.SECONDS)
.flatMap(g -> g.subscribeOn(Schedulers.computation()))

因为窗口本质上是热源, 因此可以通过observeOn将数据项的处理安全地移动到别的线程:

source.window(1, TimeUnit.SECONDS)
.flatMap(g -> 
    g.observeOn(Schedulers.computation())
    .map(v -> v + 1)
)

生成CompositeException cause

在1.x和2.x中, 调用方法CompositeException.getCause()导致从内部聚合异常列表中生成异常链. 这主要是因为Java 6缺乏Java 7+的异常抑制特性. 然而, 这些实现可能正在转换异常, 或者, 有时候, 完全不能建立起异常链. 鉴于该方法最初贡献的来源, 在2.x中修复该方法的问题是有风险的.

有了3.x, 该方法构造了一个异常原因,当该异常请求stacktrace时,会在不触及聚合异常的情况下生成输出(这个操作是IDE友好的, 应该也是可以导航的):

栈迹示例

Multiple exceptions (2)
|-- io.reactivex.rxjava3.exceptions.TestException: ex3
    at io.reactivex.rxjava3.exceptions.CompositeExceptionTest.nestedMultilineMessage(CompositeExceptionTest.java:341)
|-- io.reactivex.rxjava3.exceptions.TestException: ex4
    at io.reactivex.rxjava3.exceptions.CompositeExceptionTest.nestedMultilineMessage(CompositeExceptionTest.java:342)
  |-- io.reactivex.rxjava3.exceptions.CompositeException: 2 exceptions occurred. 
      at io.reactivex.rxjava3.exceptions.CompositeExceptionTest.nestedMultilineMessage(CompositeExceptionTest.java:337)
    |-- io.reactivex.rxjava3.exceptions.CompositeException.ExceptionOverview: 
        Multiple exceptions (2)
        |-- io.reactivex.rxjava3.exceptions.TestException: ex1
            at io.reactivex.rxjava3.exceptions.CompositeExceptionTest.nestedMultilineMessage(CompositeExceptionTest.java:335)
        |-- io.reactivex.rxjava3.exceptions.TestException: ex2
            at io.reactivex.rxjava3.exceptions.CompositeExceptionTest.nestedMultilineMessage(CompositeExceptionTest.java:336)

image

参数验证异常的更改

2.x中的一些标准操作符在对应的参数非法时会抛出IndexOutOfBoundsException. 为了与其它参数验证异常保持一致, 下面的操作符现在抛出了IllegalArgumentException:

  • skip
  • skipLast
  • takeLast
  • takeLastTimed

预先取消from回调

在2.x, 取消通过fromRunnablefromAction创建的序列是与其它fromX序列不一致的, 在下游立即取消/销毁该序列的时候.

在3.x中, 这种预先取消将不会执行给定的回调.

from回调示例

Runnable run = mock(Runnable.class);

Completable.fromRunnable(run)
.test(true); // cancel upfront

verify(run, never()).run();

使用cleanup次序

操作符usingeager参数来决定什么时候源应该被清理: true意味着在终止之前而false则意味着在终止之后. 不幸的是, 此设置不会影响取消donwstream时的清理顺序, 并且总是在取消上游之前清理资源.

在3.x中, 在序列终止或者取消的时候, 清理顺序现在是一致的: true意味着终止之前或者取消上游之前, false意味着终止之后或者取消上游之后.

引用

RxJava 3 新不同 - 1

RxJava 3 新不同 - 2

RxJava 3 新不同 - 3

RxJava 3 新不同 - 4

RxJava 3 新不同 - 5

RxJava 3 新不同 - 6

RxJava 3 新不同 - 7

RxJava 3 新不同 - 8