首页 > 解决方案 > RxJava2-除非是TimeoutException,否则如何每次重试?

问题描述

我有一个链,Observables最后,我正在通过蓝牙向设备写入命令,我正在等待通知。有一个案例,它可以永远在这里等待,所以我想使用timeout- 简单。

但问题是,我希望retry每次发生任何其他问题时,只有在timeout发生时才应该终止它 - 否则它应该retry。此外,如果我们沿着链向下走,我们将遇到其他也应该具有相同行为的重试。超时异常应该被推回更高层(在我的例子中是交互器)。

我想过,retryWhen但我不确定在这种情况下如何正确使用它。

.retryWhen { it.filter { throwable -> throwable !is TimeoutException } }

此外,很难为此编写测试,因此我更难找到正确的解决方案。

标签: androidrx-javarx-java2

解决方案


请尝试以下我用于我的项目的方法。

创建一个类(它是一个 java 类,如果需要,您可以将其更改为 kotlin)

public class RetryWithDelay implements Function<Observable<? extends Throwable>, Observable<?>> {
private static final String TAG = "RetryWithDelay";

private final int maxRetries;
private final int retryDelayInMinutes;
private int retryCount;



public RetryWithDelay(final int maxRetries, final int retryDelayInMinutes) {
    this.maxRetries = maxRetries;
    this.retryDelayInMinutes = retryDelayInMinutes;
    this.retryCount = 0;
}

@Override
public Observable<?> apply(Observable<? extends Throwable> attempts) {
    return attempts.flatMap(new Function<Throwable, Observable<?>>() {
        @Override
        public Observable<?> apply(Throwable throwable) {
            if (throwable instanceof TimeoutException) {
                return Observable.error(throwable);
            }

            if (++retryCount < maxRetries) {
                // When this Observable calls onNext, the original
                // Observable will be retried (i.e. re-subscribed).
                return Observable.timer(retryDelayInMinutes, TimeUnit.MINUTES);
            }

            // Max retries hit. Just pass the error along.
            return Observable.error(throwable);
        }
    });
}}

在 apply 方法中,它会检查异常是否是 TimeOut 的实例,它会抛出一个错误,否则它将继续重试你想要的 maxRetries。

并通过这个类如下

  .retryWhen (new RetyWithDelay(3,5)) 

它将每 5 分钟重试 3 次。


推荐阅读