Obtener el código de estado de la respuesta utilizando Retrofit 2.0 y RxJava
Estoy tratando de actualizar a Retrofit 2.0 y agregar RxJava en mi proyecto de Android. Estoy haciendo una llamada a la api y quiero recuperar el código de error en caso de una respuesta de error del servidor.
Observable<MyResponseObject> apiCall(@Body body);
Y en la llamada RxJava:
myRetrofitObject.apiCall(body).subscribe(new Subscriber<MyResponseObject>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(MyResponseObject myResponseObject) {
//On response from server
}
});
En Retrofit 1.9, el RetrofitError todavía existía y podíamos obtener el estado haciendo:
error.getResponse().getStatus()
¿Cómo se hace esto con Retrofit 2.0 usando RxJava?
3 answers
En lugar de declarar la llamada a la API como lo hiciste:
Observable<MyResponseObject> apiCall(@Body body);
También puedes declararlo así: {[19]]}
Observable<Response<MyResponseObject>> apiCall(@Body body);
Entonces tendrá un Suscriptor como el siguiente:
new Subscriber<Response<StartupResponse>>() {
@Override
public void onCompleted() {}
@Override
public void onError(Throwable e) {
Timber.e(e, "onError: %", e.toString());
// network errors, e. g. UnknownHostException, will end up here
}
@Override
public void onNext(Response<StartupResponse> startupResponseResponse) {
Timber.d("onNext: %s", startupResponseResponse.code());
// HTTP errors, e. g. 404, will end up here!
}
}
Por lo tanto, las respuestas del servidor con un código de error también se entregarán a onNext
y puede obtener el código llamando a reponse.code()
.
Http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html
EDITAR: OK, finalmente me puse a buscar en lo que e-nouri dicho en su comentario, a saber, que solo los códigos 2xx voluntad a a onNext
. Resulta que ambos tenemos razón:
Si la llamada se declara así:
Observable<Response<MyResponseObject>> apiCall(@Body body);
O incluso esto
Observable<Response<ResponseBody>> apiCall(@Body body);
Todas las respuestas terminarán en onNext
, independientemente de su código de error. Esto es posible porque todo está envuelto en un objeto Response
por Retrofit.
Si, por otro lado, la llamada se declara así: {[19]]}
Observable<MyResponseObject> apiCall(@Body body);
O esto
Observable<ResponseBody> apiCall(@Body body);
De hecho solo el 2xx las respuestas irán a onNext
. Todo lo demás será envuelto en un HttpException
y enviado a onError
. Lo que también tiene sentido, porque sin la envoltura Response
, ¿qué debería emitirse a onNext
? Dado que la solicitud no tuvo éxito, lo único sensato para emitir sería null
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-31 18:07:01
Dentro del método onError poner a esto obtener el código
((HttpException) e).code()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-17 07:27:55
Debes tener en cuenta que a partir de Retrofit2 todas las respuestas con código 2xx se llamarán desde onNext () callback y el resto de códigos HTTP como 4xx, 5xx se llamarán en el onError () callback, usando Kotlin Se me ocurrió algo como esto en el unError() :
mViewReference?.get()?.onMediaFetchFinished(downloadArg)
if (it is HttpException) {
val errorCode = it.code()
mViewReference?.get()?.onMediaFetchFailed(downloadArg,when(errorCode){
HttpURLConnection.HTTP_NOT_FOUND -> R.string.check_is_private
else -> ErrorHandler.parseError(it)
})
} else {
mViewReference?.get()?.onMediaFetchFailed(downloadArg, ErrorHandler.parseError(it))
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-23 06:36:26