如何在RxJava2中链接两个Completable

Mla*_*jac 38 java rx-java rx-java2

我有两个可完成的.我想做以下场景:如果第一个Completable到达onComplete,继续第二个Completable.最终结果将是第二次完成的完成.

当我有单个getUserIdAlreadySavedInDevice()和Completable login()时,我就是这样做的:

@Override
public Completable loginUserThatIsAlreadySavedInDevice(String password) {
    return getUserIdAlreadySavedInDevice()
            .flatMapCompletable(s -> login(password, s))

}
Run Code Online (Sandbox Code Playgroud)

Mak*_*dov 96

您正在寻找andThen运营商.

返回首先运行此Completable然后另一个可完成的Completable.

firstCompletable
    .andThen(secondCompletable)
Run Code Online (Sandbox Code Playgroud)

通常,此运算符是flatMapon 的"替代" Completable:

Completable       andThen(CompletableSource next)
<T> Maybe<T>      andThen(MaybeSource<T> next)
<T> Observable<T> andThen(ObservableSource<T> next)
<T> Flowable<T>   andThen(Publisher<T> next)
<T> Single<T>     andThen(SingleSource<T> next)
Run Code Online (Sandbox Code Playgroud)

  • 嗯,我不认为`andThen`是`flatMapCompletable`的替代品,因为`andThen`采用Completable的实例,而`flatMapCompletable`采用创建Completable的函数.前者是急切的,当你调用它时,Completable被创建,而后者Completable是在Completable完成后懒惰地构造的.有了急切的版本,你可以在前者完成之前调用构建Completable,不是吗? (4认同)
  • 这应该标记为正确答案。我遇到了与操作员相同的情况,并一直在寻找答案2天。您的答案@Maxim Ostrovidov是我想要的。谢谢! (2认同)
  • 在第一个错误的情况下,文档没有指出是否执行了第二个补全.有人知道吗? (2认同)
  • @BoD 如果流中发生任何错误 - 它会以 `onError` 事件终止。这是反应式流的一般行为。所以,回答你的问题,第二个“Completable”不会被执行。 (2认同)

Spa*_*rky 62

TL; DR:其他答案错过了一个微妙之处.使用doThingA().andThen(doThingB()),如果你想的等效concat,使用doThingA().andThen(Completable.defer(() -> doThingB()),如果你想的等价flatMap.

上面的答案是正确的,但我发现它们具有误导性,因为它们错过了关于热切评价的微妙之处.

doThingA().andThen(doThingB())doThingB()立即调用但仅订阅doThingB()当返回的observable doThingA()完成时返回的observable .

doThingA().andThen(Completable.defer(() -> doThingB())doThingB()只有在事物A完成后才会打电话.

只有doThingB()在订阅事件之前有副作用时,这才是重要的.例如Single.just(sideEffect(1)).toCompletable()

在订阅事件(真正的冷可观察)之前没有副作用的实现可能是Single.just(1).doOnSuccess(i -> sideEffect(i)).toCompletable().

如果只是咬了我的东西A是一些验证逻辑并doThingB()立即启动异步数据库更新,完成VertX ObservableFuture.这是不好的.按理说doThingB()应该写只更新在订阅数据库,我要去尝试,并在未来的设计的东西的方式.

  • 是的,这个..!这应该是公认的答案! (3认同)

Den*_*eev 5

尝试

Completable.concat

Returns a Completable which completes only when all sources complete, one after another.
Run Code Online (Sandbox Code Playgroud)

http://reactivex.io/RxJava/javadoc/io/reactivex/Completable.html#concat(java.lang.Iterable)


cam*_*pos 5

请注意,这里获得更多票数的答案有点误导。请参阅下面的示例,我的想法是展示一些测试场景并展示操作符的可完成逻辑的andThen行为方式。

 private fun doThingAFail(): Completable {
        print("Do thingA Called\n")
        return Completable.fromCallable {
            print("calling stream A\n")
            throw(Exception("The excep"))
        }
    }

    private fun doThingB(): Completable {
        print("Do thingB Called\n")
        return Completable.fromCallable {
            print("calling stream B\n")

        }
    }

    private fun doThingA(): Completable {
        print("Do thingA Called\n")
        return Completable.fromCallable {
            print("calling stream A\n")
        }
    }

Run Code Online (Sandbox Code Playgroud)

请观察以下测试:

@Test
fun testCallAPlusB() {
    doThingA().andThen(doThingB())
}
Run Code Online (Sandbox Code Playgroud)

输出将是:

Do thingA Called
Do thingB Called
Run Code Online (Sandbox Code Playgroud)

这里快速说明:请注意,我们没有订阅此代码片段中的这些 Completables。

对于测试:

@Test
fun theTestSubscribe() {
    doThingA().andThen(doThingB()).subscribe()
}
Run Code Online (Sandbox Code Playgroud)

输出将是:

Do thingA Called
Do thingB Called
calling stream A
calling stream B

Run Code Online (Sandbox Code Playgroud)

最后,如果第一个可完成失败,第二个可完成将不会被执行。

@Test
fun theTestFailThingA() {
    doThingAFail().andThen(doThingB()).subscribe()
}
Run Code Online (Sandbox Code Playgroud)

输出将是:

Do thingA Called
Do thingB Called
calling stream A
Run Code Online (Sandbox Code Playgroud)

这里的关键概念是方法内部的逻辑和可观察对象内部的逻辑不是同时执行的。doThingA()一旦我们调用和doThingB()方法,“Do thingA Called”和“Do thingB Called”行将被打印。而“调用流 A”和“调用流 B”行仅当有人订阅doThingAdoThingB方法时才会被调用。

这里的第二个概念是 andThen 运算符如何处理错误。在上面的示例中,如果doThingA()completable 最终出现错误,流将结束并且不会打印“调用流 B”行。