android - rxjava - Manejar error de red con Retrofit observable
retrofit rxjava 2 (4)
Al usar Observables con Retrofit, ¿cómo maneja la falla de la red?
Dado este código:
Observable<GetJobResponse> observable = api.getApiService().getMyData();
observable
.doOnNext(new Action1<GetJobResponse>() {
@Override
public void call(GetJobResponse getJobResponse) {
//do stuff with my data
}
})
.doOnError(new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
//do stuff with error message
}
});
La solicitud simplemente falla sin red y onError no se llama. No se bloquea, pero falla silenciosamente. Logs muestra Retrofit recibiendo el error:
java.net.UnknownHostException: Unable to resolve host "api-staging.sittercity.com": No address associated with hostname
at java.net.InetAddress.lookupHostByName(InetAddress.java:424)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
at java.net.InetAddress.getAllByName(InetAddress.java:214)
at com.squareup.okhttp.internal.Dns$1.getAllByName(Dns.java:29)
Usando devoluciones de llamada, esto simplemente se pasa a onFailure (error RetrofitError). ¿Cómo puedo hacer que esto salga a la superficie con RxJava?
A partir de Retrofit2
y RxJava2
no hay más excepciones RetrofitError
. Y su sucesor HttpException
solo representa los códigos de respuesta de error HTTP. Los errores de red deben manejarse a través de IOException
.
@Override
public void onError(Throwable e) {
if (e instanceof IOException) {
//handle network error
} else if (e instanceof HttpException) {
//handle HTTP error response code
} else {
//handle other exceptions
}
}
Esto es puramente un problema de RxJava, que no implica mucho de Retrofit. doOnError
es un efecto secundario, por lo que, aunque maneja el error, no se "atrapa" en el sentido de evitar que burbujee hacia adelante.
Usted debe mirar a los operadores de manejo de errores . La opción más básica es onErrorReturn()
que le permite sustituir un error con un elemento (instancia de GetJobResponse
).
Puede colocar un indicador de "error" en ese elemento para identificarlo más adelante cuando se suscriba al observable
. También es importante saber que si no te suscribes a ese observable, es esencialmente "muerto". Siempre debe suscribirse a observables en lugar de usar "doOn___", que son solo efectos secundarios (debe usarse para el registro y otras funciones no críticas).
Mi problema estaba realmente en otro lugar en mi código. El manejo de errores de red con rxJava + Retrofit es muy fácil ya que simplemente lanza un RetrofitError en el método onError:
@Override
public void onError(Throwable e) {
if (e instanceof RetrofitError) {
if (((RetrofitError) e).isNetworkError()) {
//handle network error
} else {
//handle error message from server
}
}
}
Tenga en cuenta que si deja que un observable emita onError
, todos los observables en sentido ascendente se apagarán, independientemente de si lo "captura" con onErrorReturn
o onErrorResumeNext
. A menudo no quieres eso. Por ejemplo, si su transmisión comienza con un clic en el botón que activa una solicitud de modificación que falla, los clics en los botones ya no serán reconocidos ya que la transmisión terminó.
Use Observable<Response<Type>>
u Observable<Result<Type>>
para manejar también los errores de modificación en onNext()
.
s. http://blog.danlew.net/2015/12/08/error-handling-in-rxjava/