2015-09-18 17 views
5

Mam następujący Obserwowalne który wykona odpocząć-Call z modernizacją co 30 sekund:RxJava dla Androida: Expose wyjątek i ponowić (z opóźnieniem)

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()); 

Może się zdarzyć, że (zwłaszcza REST-Call) rzuci wyjątek (np. brak połączenia z Internetem).

Co chciałbym osiągnąć:

obserwowalnym powinien emitować/wystawiać wyjątek, tak że mogę wyświetlić komunikat o błędzie w interfejsie, lecz powinien on kontynuować emitując przedmioty (ponownie w ciągu 30 sekund) .

Obecnie badania

  • Gdybym nie określają żadnego szczególnego zachowania obserwowalnego emituje wyjątek i przestanie działać (= NO ponownych prób w ciągu 30 sekund).

  • Jeśli spróbuję ponownie uruchomić operatora, wyjątek zostanie połknięty i nie jest narażony, więc nie mogę wyświetlić błąd w interfejsie użytkownika.

  • Jeśli wypróbuję operatora onErrorReturn, mogę obsłużyć wyjątek, ale nie można ponowić próby, o ile wiem.

Obejście

Moje bieżące obejście jest ponownie zapisać się do tego Obserwowalne, ale chciałbym wiedzieć, czy ktoś ma bardziej eleganckie rozwiązanie.

Odpowiedz

4

Jestem zakładając doOnError zmieści swoje potrzeby (do logowania błąd), w połączeniu z ponownego wprowadzenia, na przykład:

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()); 
+0

Cool, dzięki! – Christopher

1

Z pomocą drugiej odpowiedzi, jeśli znalazł rozwiązanie.

Najpierw zdefiniowałem funkcję RetryWithDelay, która rozpoczyna ponowną próbę po 30 sekundach, a nie natychmiast.

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,    } 
    }); 
    } 
} 

Które I następnie wykorzystywane w tym obserwowalnych-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());