Christopher
Christopher

Reputation: 10259

RxJava for Android: Expose Exception and Retry (with delay)

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

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

Answers (2)

Christopher
Christopher

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

Gluck
Gluck

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

Related Questions