Reputation: 10259
I have the following Observable which will execute a REST-Call with Retrofit each 30 seconds:
Subscription subscription = Observable.interval(0, REFRESH_INTERVAL, TimeUnit.SECONDS)
.concatMap(new Func1<Long, Observable<Response>>() {
@Override
public Observable<Response> call(Long time) {
return webservice.callRetrofitServiceWithRx(parameter);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new UpdateSuccessAction(), new UpdateErrorAction());
It may happen that (especially the REST-Call) will throw an exception (e.g. no internet connection).
What I would like to achieve:
The Observable should emit/expose the exception, so that I can display an error message on the UI, but it should continue emitting items (retry in 30 seconds).
Currently research
If I do not define any special behaviour the Observable emits the Exception and stops working (= NO retry in 30 seconds).
If I try the retry operator, the exception will be swallowed and not exposed, so I can not display an error in the ui.
If I try the onErrorReturn operator, I can handle the exception, but no retry is possible as far as I know.
Workaround
My current workaround is to re-subscribe to this Observable, but I would like to know if someone has a more elegant solution.
Upvotes: 6
Views: 1523
Reputation: 10259
With the help of the other answer if found a solution.
At first I defined a RetryWithDelay-Function which starts the retry after 30 seconds and not immediately.
private static class RetryWithDelay
implements Func1<Observable<? extends Throwable>, Observable<?>> {
@Override
public Observable<?> call(Observable<? extends Throwable> attempts) {
return attempts.flatMap(new Func1<Throwable, Observable<?>>() {
@Override
public Observable<?> call(Throwable throwable) {
return Observable.timer(CallBO.REFRESH_INTERVAL_IN_SEC, }
});
}
}
Which I then used in this Observable-Chain:
Subscription subscription = Observable.interval(0, REFRESH_INTERVAL, TimeUnit.SECONDS)
.concatMap(new Func1<Long, Observable<Response>>() {
@Override
public Observable<Response> call(Long time) {
return webservice.callRetrofitServiceWithRx(parameter);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError(new UpdateErrorAction())
.retryWhen(new RetryWithDelay())
.subscribe(new UpdateSuccessAction());
Upvotes: 1
Reputation: 2962
I'm assuming doOnError will fit your need (for logging the error), combined with retry, e.g:
Subscription subscription = Observable.interval(0, REFRESH_INTERVAL, TimeUnit.SECONDS)
.concatMap(new Func1<Long, Observable<Response>>() {
@Override
public Observable<Response> call(Long time) {
return webservice.callRetrofitServiceWithRx(parameter);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError(new UpdateErrorAction())
.retry()
.subscribe(new UpdateSuccessAction());
Upvotes: 4