结合RxJava Completables

Combining RxJava Completables

1.概述

在本教程中,我们将使用RxJava的Completable类型,该类型表示没有实际值的计算结果。

2. RxJava依赖关系

让我们将RxJava 2依赖项包含到我们的Maven项目中:

1
2
3
4
5
<dependency>
    <groupId>io.reactivex.rxjava2</groupId>
    <artifactId>rxjava</artifactId>
    <version>2.2.2</version>
</dependency>

我们通常可以在Maven Central上找到最新版本。

3.完成类型

Completable与Observable相似,唯一的例外是前者发出完成或错误信号,但不发出任何项目。 Completable类包含几种方便的方法,可用于从不同的反应性源创建或获取它。

我们可以使用Completable.complete()生成立即完成的实例。

然后,我们可以使用DisposableCompletableObserver观察其状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
Completable
  .complete()
  .subscribe(new DisposableCompletableObserver() {
    @Override
    public void onComplete() {
        System.out.println("Completed!");
    }

    @Override
    public void onError(Throwable e) {
        e.printStackTrace();
    }
});

另外,我们可以从Callable,Action和Runnable构造一个Completable实例:

1
Completable.fromRunnable(() -> {});

另外,我们可以使用Completable.from()或在Maybe,Single,Flowable和Observable源自身上调用ignoreElement()来从其他类型获取Completableinstances:

1
2
3
4
5
6
Flowable<String> flowable = Flowable
  .just("request received","user logged in");
Completable flowableCompletable = Completable
  .fromPublisher(flowable);
Completable singleCompletable = Single.just(1)
  .ignoreElement();

4.链接完成项

当我们只在乎操作的成功时,我们可以在许多实际的用例中使用Completables的链接:

  • 一无所有的操作,例如执行PUT请求以更新远程对象,然后在成功后更新本地数据库

  • 事后记录和日记

  • 编排几个动作,例如 提取动作完成后运行分析工作

  • 我们将使示例简单且与问题无关。 考虑一下我们有几个Completable实例:

    1
    2
    3
    4
    5
    6
    7
    Completable first = Completable
      .fromSingle(Single.just(1));
    Completable second = Completable
      .fromRunnable(() -> {});
    Throwable throwable = new RuntimeException();
    Completable error = Single.error(throwable)
      .ignoreElement();

    要将两个Completables组合为一个,我们可以使用theandThen()运算符:

    1
    2
    3
    4
    first
      .andThen(second)
      .test()
      .assertComplete();

    我们可以根据需要链接任意多个Completables。 同时,如果至少一个源未能完成,则resultCompletable也将不会触发onComplete():

    1
    2
    3
    4
    5
    first
      .andThen(second)
      .andThen(error)
      .test()
      .assertError(throwable);

    此外,如果源之一是无限的,或者由于某种原因未到达onComplete,则resultCompletable也将永远不会触发fireonComplete()noronError()。

    一件好事,我们仍然可以测试这种情况:

    1
    2
    3
    4
    ...
      .andThen(Completable.never())
      .test()
      .assertNotComplete();

    5.组成一系列可完成项目

    想象一下,我们有一堆Completables。 作为实际用例,假设我们需要在几个单独的子系统中注册用户。

    要将allCompletables合并为一个,我们可以使用它们的erge()系列方法。 merge()运算符允许订阅所有源。

    一旦所有源都完成,结果实例将完成。 此外,当任何源发出错误时,它会以onError终止:

    1
    2
    3
    4
    5
    6
    7
    Completable.mergeArray(first, second)
      .test()
      .assertComplete();

    Completable.mergeArray(first, second, error)
      .test()
      .assertError(throwable);

    让我们继续一个稍微不同的用例。 假设我们需要对从aFlowable获得的每个元素执行一个动作。

    然后,我们希望对上游操作的完成和所有元素级操作都使用singleCompletable。 在这种情况下,flatMapCompletable()运算符可为您提供帮助:

    1
    2
    3
    4
    5
    6
    7
    8
    Completable allElementsCompletable = Flowable
      .just("request received","user logged in")
      .flatMapCompletable(message -> Completable
          .fromRunnable(() -> System.out.println(message))
      );
    allElementsCompletable
      .test()
      .assertComplete();

    类似地,以上方法可用于其余的基本反应性类,如Observable,Maybe或Single。

    作为flatMapCompletable()的实用上下文,我们可以考虑对每一项进行装饰并产生一些副作用。 我们可以为每个完成的元素编写一个日志条目,或者在每次成功操作后制作一个存储快照。

    最后,我们可能需要从其他两个来源构造一个Completable,并在其中任何一个完成时立即终止它。 这就是支持者提供帮助的地方。

    Theamb前缀是"歧义"的简写,表示不确定哪个Completable完全完成。 例如,ambArray():

    1
    2
    3
    Completable.ambArray(first, Completable.never(), second)
      .test()
      .assertComplete();

    请注意,取决于哪个源可完成对象首先终止,上述completeCompletable也可以使用onError()代替onComplete()终止:

    1
    2
    3
    Completable.ambArray(error, first, second)
      .test()
      .assertError(throwable);

    同样,一旦第一个信号源终止,就保证其余的信号源都将被丢弃。

    这意味着将通过Disposable.dispose()停止所有剩余的runningCompletables,并且相应的CompletableObservers将被取消订阅。

    关于一个实际示例,当我们将备份文件流式传输到几个等效的远程存储时,可以使用amb()。 最好的备份完成后,我们将完成该过程,或者在出现错误时重复该过程。

    六,结论

    在本文中,我们简要回顾了RxJava的Completable类型。

    我们从获取Completable实例的不同选项开始,然后通过使用andThen(),merge(),flatMapCompletable()和amb…()运算符来链接和组合Completables。

    我们可以在GitHub上找到所有代码示例的源代码。