我正在升级到rxjava2,我们有代码来从服务器轮询数据,代码处理在网络问题时重试延迟。但是,当我尝试迁移到rxjava2时,代码停止工作。 以下是Rxjava1的代码,其工作正常,基本上遵循此http://blog.danlew.net/2015/03/02/dont-break-the-chain/和此https://medium.com/@v.danylo/server-polling-and-retrying-failed-operations-with-retrofit-and-rxjava-8bcc7e641a5a
.retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
@Override
public Observable<?> call(final Observable<? extends Throwable> observable) {
// wrap a flatmap here so that i can check the exception type
return observable.flatMap(new Func1<Throwable, Observable<?>>() {
@Override
public Observable<?> call(Throwable throwable) {
mThrowable = throwable;
if (throwable instanceof IOException) {
return observable.compose(timerWithRetries());
} else {
// for other errors, call onError and exit
return Observable.error(throwable);
}
}
});
}
})
private <T> Observable.Transformer<T, Long> timerWithRetries() {
return new Observable.Transformer<T, Long>() {
@Override
public Observable<Long> call(Observable<T> observable) {
return observable
.zipWith(Observable.range(COUNTER_START, MAX_RETRIES + 1),
new Func2<T, Integer, Integer>() {
@Override
public Integer call(T t, Integer repeatAttempt) {
return repeatAttempt;
}
})
.flatMap(new Func1<Integer, Observable<Long>>() {
@Override
public Observable<Long> call(Integer repeatAttempt) {
if (repeatAttempt == MAX_RETRIES + 1) {
if (mThrowable instanceof IOException) {
// Custom Exception
throw new Exception();
}
}
// increase the waiting time
return Observable.timer(repeatAttempt * mDelaySeconds, TimeUnit.SECONDS);
}
});
}
};
}
我想用flatmap包装错误,以便我可以检查异常类型,当它达到最大重试次数时,我可以将自定义异常传递给onError。
但是,当只使用Rxjava2时,timerWithRetries()方法停止工作,调用此方法但不执行.zipWith()及其flatmap。
但是它在包装错误时没有使用flatmap,这很奇怪。像
这样的东西.retryWhen(error -> error.compose(timerWithRetries()))
非常赞赏任何建议!
答案 0 :(得分:2)
1.x retryWhen
使用保留在最后一个Throwable上的BehaviorSubject
,并在有新订阅者时重播。这主要是由于它的“怪异”和#34;通过尝试支持大多数retry
和repeat
运营商来实施。
2.x使用PublishSubject
并且通常只订阅一次(不再重新组合)。只有失败时的观察者才会收到错误值,但不会收到错误发射后的任何错误值。
实际上,observable.compose(timerWithRetries());
并不完全正确,因为您不断向主题添加观察者而不清除之前的观察者。
最后一种情况是有效的,因为你使用count-flatMapped处理程序构建主要错误源,该处理程序作为对原始错误的响应而发出。
答案 1 :(得分:0)
我终于找到了解决方法。使用延迟()而不是使用zipWith()和flatmap()。
AtomicInteger retryCounter = new AtomicInteger(0);
.retryWhen(error -> error.flatmap(e -> {
if (e instanceof HttpException) {
// code that deals with specific exception
int retries = retryCounter.increaseAndGet();
if (retries < MAX_RETRIES) {
// Key point here, uses .delay()
return Observable.just(new Object()).delay(delaySeconds, SECOND);
}
}
}))