使用Rx调用两个链式独立方法

时间:2018-06-24 21:21:57

标签: android rx-java rx-android

我有两个异步方法,必须在一次操作中调用它。每种方法都可以成功完成,或者会出错。如果出现错误,我必须重试2秒以再次尝试调用每个方法。意思是,尽管其中一个方法有结果,但我应该同时调用这两个方法。在错误回调中,我想知道发生在哪种方法中的错误,或两种方法中都发生了错误。

似乎我应该为此使用Completable,但在Rx中我绝对是新手。

private void method1(final CompletableEmitter e, String path){
Database.getInstance().getReference(path).addListener(new Listener() {
            @Override
            public void onDataChange(Data data) {
               //todo something
               e.onComplete();                
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
               e.onError(new Throwable(databaseError.getMessage()));
            }
        });
}

方法2相同。 以下代码无法正常工作。

    Completable completable1 = Completable.create(method1(e););
    Completable completable2 = Completable.create(method2(e););

    completable1
            .doOnError(…)
            .retry(1)
            .andThen(completable2 //never called if completable1 gets onError each time
                    .retry(1)
                    .doOnError(…))
            .subscribe(…).dispose();

1 个答案:

答案 0 :(得分:1)

您有很多方法可以做到这一点。我仅是为了解释一下如何使用两个Completable

假设您有两个完成项:

Completable doSomething = ...
Completable doSomethingElse = ...

要顺序执行这些命令, 您可以使用andThen运算符来连接它们。然后,要在发生错误时延迟重试,可以使用retryWhen

doSomething.andThen(doSomethingElse)
    .retryWhen { Flowable.timer(2, TimeUnit.SECONDS) }
    .subscribe()

如果永久性发生错误,则以上代码段将无限重试。要超越此限制,您可以使用以下方法限制尝试次数:

.retryWhen { errors ->
    val retryCounter = AtomicInteger()
    errors.flatMap {
        if (retryCounter.getAndIncrement() <= 3)
            Flowable.timer(2, TimeUnit.SECONDS)
        else Flowable.error(it)
    }
}

如果仅在发生给定类型的错误时才想重试,则可以使用:

.retryWhen { errors ->
    val retryCounter = AtomicInteger()
    errors.flatMap {
        if (it is YourSpecficError && retryCounter.getAndIncrement() <= 3)
            Flowable.timer(2, TimeUnit.SECONDS)
        else Flowable.error(it)
    }
}

如果要独立重试每个,则可以使用:

doSomething.retryWhen { ... }
    .andThen(doSomethingElse.retryWhen { ... })
    .subscribe()

此外,为了避免重试逻辑重复,您可以将其封装在扩展函数中:

fun Completable.retryDelayed(): Completable {
    return this.retryWhen { errors ->
        val retryCounter = AtomicInteger()
        errors.flatMap {
            if (it is YourSpecficError && retryCounter.getAndIncrement() <= 3)
                Flowable.timer(2, TimeUnit.SECONDS)
            else Flowable.error(it)
        }
    }
}

如果要并行运行互补项,则可以使用merge运算符:

Completable doAll = Completable.merge(listOf(doSomething, doSomething))