2015-09-18 6 views
5

Ich habe folgendes Observable, die ein REST-Aufruf mit Retrofit ausführen werden jeweils 30 Sekunden:RxJava für Android: Expose Ausnahme und Retry (mit Verzögerung)

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

es passiert, dass kann (vor allem des REST-Aufruf) wird eine Ausnahme auslösen (zB keine Internetverbindung).

Was möchte ich erreichen möchte:

Die beobachtbare sollte die Ausnahme emittieren/aussetzen, so dass ich eine Fehlermeldung auf der Benutzeroberfläche angezeigt werden können, aber es sollte Artikel weiter emittieren (Wiederholung in 30 Sekunden) .

Aktuelle Forschung

  • Wenn ich die beobachtbaren geben das Exception kein spezielles Verhalten definieren und nicht mehr funktionieren (= keine Wiederholung in 30 Sekunden).

  • Wenn ich den Wiederholungsversuch versuche, wird die Ausnahme verschluckt und nicht ausgesetzt, so dass ich keinen Fehler in der ui anzeigen kann.

  • Wenn ich den onErrorReturn-Operator versuche, kann ich die Ausnahme behandeln, aber soweit ich weiß, ist keine Wiederholung möglich.

Umgehung

Meine aktuelle Problemumgehung ist auf diese beobachtbare wieder anmelden, aber ich würde gerne wissen, ob jemand eine elegantere Lösung.

Antwort

4

Ich gehe davon aus doOnError wird Ihren Bedarf (zum Protokollieren des Fehlers), kombiniert mit Wiederholungs passen, z:

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, vielen Dank! – Christopher

1

Mit Hilfe der anderen Antwort, wenn eine Lösung gefunden.

Zuerst habe ich eine RetryWithDelay-Funktion definiert, die den Retry nach 30 Sekunden und nicht sofort startet.

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

die ich dann in dieser Observable-Kette verwendet:

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