RxJava2 - 如何重试每次除非它的TimeoutException异常?

时间:2019-02-01 09:18:08

标签: android rx-java rx-java2

我有一个Observables链,最后,我正在通过蓝牙向设备写入命令,并且正在等待通知。有一个情况下,它可以永远在这里等待,所以我想用timeout - 容易。

但是问题是,我想每次retry发生任何其他问题时,都应仅在发生timeout时终止它,否则应该retry。同样,如果我们沿着链条走下去,我们将遇到其他也应该具有相同行为的重试。超时异常应推回到更高的层(在我的情况下为交互器)。

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

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

此外,这是很难写测试,对于这样就更难为我找到合适的解决方案。

1 个答案:

答案 0 :(得分:1)

请尝试以下我在项目中使用的方法。

创建一个类(这是一个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次。