In diesem Artikel wird
RxJava2
in
RxJava2
Version
2.0.6
und
RxJava2
2.0.6
. Wenn jemand zusammengestoßen ist und es nicht herausfinden kann oder überhaupt nichts von diesem Problem gehört hat, bitte ich um eine Katze. Sie veranlassten die Übersetzung von Problemen in der
production
nach dem Übergang von
RxJava1
zu
RxJava2
. Das Original wurde am 28. Dezember 2017 geschrieben, aber es ist besser, es spät herauszufinden als nie.
Wir sind alle gute Entwickler und fangen Fehler in
onError
wenn wir
RxJava
. Das heißt, wir haben uns vor Anwendungsabstürzen geschützt, oder?
Nein, nicht wahr.Im Folgenden werden einige Beispiele aufgeführt, in denen die Anwendung aufgrund von
RxJava
, selbst wenn
onError
korrekt implementiert ist.
Grundlegende RxJava
in RxJava
RxJava
verwendet
RxJavaPlugins.onError
als
RxJavaPlugins.onError
. Es behandelt alle Fehler, die nicht an den Teilnehmer übermittelt werden können. Standardmäßig werden alle Fehler an das Programm gesendet, sodass kritische Anwendungsabstürze auftreten können.
2.0.6
beschreiben dieses Verhalten:
Eines der Ziele des 2.x-Designs ist das Fehlen verlorener Fehler. Manchmal endet eine Sequenz oder wird abgebrochen, bevor die Quelle onError
. In diesem Fall kann der Fehler nicht RxJavaPlugins.onError
und wird an RxJavaPlugins.onError
Wenn RxJava keinen grundlegenden Fehlerbehandler hat, werden solche Fehler vor uns verborgen und die Entwickler werden über mögliche Probleme im Code im Dunkeln bleiben.
Ab Version
2.0.6
versucht
2.0.6
,
RxJavaPlugins.onError
zu sein, und teilt Bibliotheks- / Implementierungsfehler und Situationen, in denen ein Fehler nicht
RxJavaPlugins.onError
werden kann. Fehler, die der Kategorie „Bugs“ zugewiesen sind, werden
UndeliverableException
aufgerufen, während der Rest in
UndeliverableException
und dann aufgerufen wird. Sie können all diese Logik
hier sehen (
onError
und
isBug
).
Einer der
RxJava
Neulinge in der
RxJava
ist
OnErrorNotImplementedException
. Dieser Fehler tritt auf, wenn
observable
einen Fehler verursacht und die
onError
Methode nicht im Abonnenten implementiert ist. Dieser Fehler ist ein Beispiel für einen Fehler, der für den grundlegenden Fehlerbehandler
RxJava
ein "Fehler" ist und nicht zu einer
UndeliverableException
.
UndeliverableException
Da Fehler im Zusammenhang mit „Fehlern“ leicht zu beheben sind, werden wir uns nicht mit ihnen befassen. Die Fehler, die
RxJava
in eine
RxJava
sind interessanter, da möglicherweise nicht immer klar ist, warum der Fehler nicht an
onError
.
Die Fälle, in denen dies passieren kann, hängen davon ab, was die Quellen und Abonnenten speziell tun. Wir werden die folgenden Beispiele betrachten, aber im Allgemeinen können wir sagen, dass ein solcher Fehler auftritt, wenn es keinen aktiven Teilnehmer gibt, an den der Fehler geliefert werden kann.
Beispiel mit zipWith ()
Die erste Option, mit der Sie eine
zipWith
können, ist die
zipWith
.
val observable1 = Observable.error<Int>(Exception()) val observable2 = Observable.error<Int>(Exception()) val zipper = BiFunction<Int, Int, String> { one, two -> "$one - $two" } observable1.zipWith(observable2, zipper) .subscribe( { System.out.println(it) }, { it.printStackTrace() } )
Wir kombinieren zwei Quellen miteinander, von denen jede einen Fehler verursacht. Was erwarten wir? Wir können davon ausgehen, dass
onError
zweimal aufgerufen wird, dies widerspricht jedoch
der Spezifikation für Reactive streams
.
Nach einem einzelnen Aufruf eines Terminalereignisses ( onError
, onCompelete
) müssen keine weiteren Anrufe mehr getätigt werden
Es stellt sich heraus, dass mit einem einzigen Aufruf von
onError
zweiter Aufruf nicht mehr möglich ist. Was passiert, wenn ein zweiter Fehler in der Quelle auftritt? Es wird an
RxJavaPlugins.onError
geliefert.
Eine einfache Möglichkeit, in diese Situation zu gelangen, besteht darin, Netzwerkanrufe mit
zip
zu kombinieren (z. B. zwei
Retrofit
Anrufe, die
Observable
). Wenn bei beiden Aufrufen ein Fehler auftritt (z. B. besteht keine Internetverbindung), verursachen beide Quellen Fehler, von denen die erste in die
onError
Implementierung fällt und die zweite an den
RxJavaPlugins.onError
(
RxJavaPlugins.onError
)
RxJavaPlugins.onError
.
ConnectableObservable-Beispiel ohne Abonnenten
ConnectableObservable
kann auch eine
ConnectableObservable
. Es sei daran erinnert, dass
ConnectableObservable
Ereignisse unabhängig von der Anwesenheit aktiver Abonnenten
ConnectableObservable
Sie einfach die
connect()
-Methode auf. Wenn in
ConnectableObservable
ein Fehler auftritt, wenn keine Abonnenten vorhanden sind, wird er an den
ConnectableObservable
.
Hier ist ein ziemlich unschuldiges Beispiel, das einen solchen Fehler verursachen könnte:
someApi.retrofitCall()
Wenn
someApi.retrofitCall()
einen Fehler verursacht (z. B. besteht keine Internetverbindung), stürzt die Anwendung ab, da der Netzwerkfehler an den
RxJava
wird.
Dieses Beispiel scheint fiktiv zu sein, aber es ist sehr einfach, in eine Situation zu geraten, in der
ConnectableObservable
noch verbunden ist, aber keine Abonnenten hat. Ich bin darauf
autoConnect()
als
autoConnect()
beim Aufrufen einer API
autoConnect()
.
autoConnect()
deaktiviert
Observable
nicht automatisch. Ich habe die
onStop
Activity
abgemeldet, aber das Ergebnis des Netzwerkaufrufs, der nach der Zerstörung der
Activity
und der Anwendung
UndeliverableException
mit
UndeliverableException
.
Fehlerbehandlung
Was tun mit diesen Fehlern?
Der erste Schritt besteht darin, die auftretenden Fehler zu untersuchen und festzustellen, was sie verursacht. Ideal, wenn Sie das Problem an der Quelle beheben können, um zu verhindern, dass der Fehler an
RxJavaPlugins.onError
.
Die Lösung für das Beispiel
zipWith
besteht darin, eine oder beide Quellen zu verwenden und
eine der Methoden zum Abfangen von Fehlern in ihnen zu implementieren. Beispielsweise können Sie
onErrorReturn
, um den Standardwert anstelle eines Fehlers zu übergeben.
Das
ConnectableObservable
Beispiel ist einfacher zu beheben.
ConnectableObservable
Sie lediglich sicher, dass Sie
Observable
trennen, wenn sich der letzte Abonnent abmeldet.
autoConnect()
verfügt beispielsweise über eine überladene Implementierung, die eine Funktion übernimmt, die die Verbindungszeit
erfasst (
mehr finden Sie hier ).
Eine andere Möglichkeit, das Problem zu lösen, besteht darin, den Basisfehlerbehandler durch Ihren eigenen zu ersetzen. Die
RxJavaPlugins.setErrorHandler(Consumer<Throwable>)
hilft Ihnen dabei. Wenn dies die für Sie richtige Lösung ist, können Sie alle an
RxJavaPlugins.onError
gesendeten Fehler
RxJavaPlugins.onError
und nach
RxJavaPlugins.onError
behandeln. Diese Lösung kann sehr kompliziert sein - denken
RxJavaPlugins.onError
daran, dass
RxJavaPlugins.onError
Fehler von allen
RxJava
Streams in der Anwendung empfängt.
Wenn Sie Ihre
Observable
manuell erstellen, können Sie
emitter.tryOnError()
anstelle von
emitter.tryOnError()
. Diese Methode meldet einen Fehler nur, wenn der Stream nicht beendet ist und Abonnenten hat. Denken Sie daran, dass diese Methode experimentell ist.
Die Moral dieses Artikels ist, dass Sie nicht sicher sein können, dass bei der Arbeit mit RxJava keine Fehler auftreten, wenn Sie einfach
onError
in Abonnenten implementiert
onError
. Sie sollten sich der Situationen bewusst sein, in denen Abonnenten möglicherweise keine Fehler zur Verfügung stehen, und sicherstellen, dass diese Situationen behandelt werden.