Ich verwende rxjava in meiner Android-App, um Netzwerkanforderungen asynchron zu verarbeiten. Jetzt möchte ich eine fehlgeschlagene Netzwerkanforderung erst nach Ablauf einer bestimmten Zeit wiederholen.
Gibt es eine Möglichkeit, retry () auf einem Observable zu verwenden, aber erst nach einer bestimmten Verzögerung erneut zu versuchen?
Gibt es eine Möglichkeit, dem Observable mitzuteilen, dass es gerade wiederholt wird (im Gegensatz zum ersten Versuch)?
Ich habe mir debounce () / throttleWithTimeout () angesehen, aber sie scheinen etwas anderes zu tun.
Bearbeiten:
Ich glaube, ich habe einen Weg gefunden, dies zu tun, aber ich würde mich entweder für die Bestätigung interessieren, dass dies der richtige Weg ist, oder für andere, bessere Wege.
Was ich tue, ist Folgendes: In der call () -Methode meines Observable.OnSubscribe lasse ich den Thread einfach für die gewünschte Zeit schlafen, bevor ich die Methode Subscribers onError () aufrufe. Um es alle 1000 Millisekunden erneut zu versuchen, mache ich ungefähr so:
@Override
public void call(Subscriber<? super List<ProductNode>> subscriber) {
try {
Log.d(TAG, "trying to load all products with pid: " + pid);
subscriber.onNext(productClient.getProductNodesForParentId(pid));
subscriber.onCompleted();
} catch (Exception e) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e.printStackTrace();
}
subscriber.onError(e);
}
}
Da diese Methode ohnehin auf einem E / A-Thread ausgeführt wird, wird die Benutzeroberfläche nicht blockiert. Das einzige Problem, das ich sehen kann, ist, dass selbst der erste Fehler mit Verzögerung gemeldet wird, sodass die Verzögerung auch dann vorhanden ist, wenn keine Wiederholung () erfolgt. Ich würde es besser finden, wenn die Verzögerung nicht nach einem Fehler, sondern vor einem erneuten Versuch angewendet würde (aber natürlich nicht vor dem ersten Versuch).
Error:(73, 20) error: incompatible types: RetryWithDelay cannot be converted to Func1<? super Observable<? extends Throwable>,? extends Observable<?>>
RetryWithDelay
diese: pastebin.com/6SiZeKnCInspiriert von Pauls Antwort und wenn Sie sich nicht mit
retryWhen
Problemen befassen , die von Abhijit Sarkar angegeben wurden , ist der einfachste Weg, die erneute Anmeldung mit rxJava2 bedingungslos zu verzögern:Möglicherweise möchten Sie weitere Beispiele und Erklärungen zu retryWhen und repeatWhen sehen .
quelle
Dieses Beispiel funktioniert mit jxjava 2.2.2:
Wiederholen Sie dies unverzüglich:
Wiederholen Sie den Vorgang mit Verzögerung:
Unsere Quellensingle schlägt fehl, wenn someConnection.send () fehlschlägt. In diesem Fall wird der Fehler durch die Beobachtung von Fehlern in retryWhen ausgegeben. Wir verzögern diese Emission um 300 ms und senden sie zurück, um einen erneuten Versuch zu signalisieren. take (5) garantiert, dass unsere beobachtbare Signalisierung endet, nachdem wir fünf Fehler erhalten haben. retryWhen die Beendigung sieht und nach dem fünften Fehler nicht erneut versucht wird.
quelle
Dies ist eine Lösung, die auf den von mir gesehenen Snippets von Ben Christensen, RetryWhen Example und RetryWhenTestsConditional basiert (ich musste wechseln
n.getThrowable()
,n
damit es funktioniert). Ich habe evant / gradle-retrolambda verwendet , damit die Lambda-Notation auf Android funktioniert, aber Sie müssen keine Lambdas verwenden (obwohl dies sehr zu empfehlen ist). Für die Verzögerung habe ich exponentielles Backoff implementiert, aber Sie können dort jede gewünschte Backoff-Logik einstecken. Der Vollständigkeit halber habe ich die OperatorensubscribeOn
und hinzugefügtobserveOn
. Ich benutze ReactiveX / RxAndroid für dieAndroidSchedulers.mainThread()
.quelle
Observable
Objekte wiederverwenden kann ?kjones
Lösung verwendet und sie funktioniert perfekt für mich, dankeAnstatt MyRequestObservable.retry zu verwenden, verwende ich eine Wrapper-Funktion retryObservable (MyRequestObservable, retrycount, Sekunden), die eine neue Observable zurückgibt, die die Indirektion für die Verzögerung behandelt, damit ich dies tun kann
quelle
retryWhen
ist ein komplizierter, vielleicht sogar fehlerhafter Bediener. Das offizielle Dokument und mindestens eine Antwort hier verwenden denrange
Operator, der fehlschlägt, wenn keine erneuten Versuche durchgeführt werden müssen. Siehe meine Diskussion mit ReactiveX-Mitglied David Karnok.Ich verbessern auf kjones' Antwort , indem
flatMap
aufconcatMap
und durch eine Zugabe vonRetryDelayStrategy
Klasse.flatMap
Die Reihenfolge der Emissionen bleibt dabei nicht erhaltenconcatMap
, was für Verzögerungen beim Zurücksetzen wichtig ist. DieRetryDelayStrategy
, wie der Name schon sagt, wollen wir die Benutzer von verschiedenen Arten der Erzeugung von Wiederholungsverzögerungen wählen, einschließlich Back-off. Der Code ist auf meinem GitHub verfügbar und enthält die folgenden Testfälle:Siehe
setRandomJokes
Methode.quelle
Mit RxJava Version 1.0+ können Sie jetzt zipWith verwenden, um einen erneuten Versuch mit Verzögerung zu erzielen.
Hinzufügen von Änderungen zu kjones Antwort.
Geändert
quelle
Gleiche Antwort wie von kjones, jedoch auf die neueste Version aktualisiert. Für RxJava 2.x- Version: ('io.reactivex.rxjava2: rxjava: 2.1.3')
Verwendung:
// Wiederholungslogik zu vorhandenem Observable hinzufügen. // Maximal 3 Mal mit einer Verzögerung von 2 Sekunden wiederholen.
quelle
Basierend auf kjones hier beantworten ist Kotlin Version von RxJava 2.x Neuversuch mit einer Verzögerung als Erweiterung. Ersetzen
Observable
, um dieselbe Erweiterung für zu erstellenFlowable
.Dann benutze es einfach auf beobachtbar
observable.retryWithDelay(3, 1000)
quelle
Single
?flatMap
es verwendet werden mussFlowable.timer
undFlowable.error
obwohl die Funktion istSingle<T>.retryWithDelay
.Sie können eine Verzögerung in der Observable hinzufügen, die im Operator retryWhen zurückgegeben wird
Weitere Beispiele finden Sie hier. https://github.com/politrons/reactive
quelle
Mach es einfach so:
quelle
Für Kotlin & RxJava1 Version
quelle
(Kotlin) Ich habe den Code mit exponentiellem Backoff und angewandter Verteidigungsemission von Observable.range () ein wenig verbessert:
quelle
Für den Fall, dass Sie die Anzahl der Wiederholungen ausdrucken müssen, können Sie das Beispiel auf der Wiki-Seite von Rxjava unter https://github.com/ReactiveX/RxJava/wiki/Error-Handling-Operators verwenden
quelle