Ответ 1
Вместо объявления API-вызова, как вы это делали:
Observable<MyResponseObject> apiCall(@Body body);
Вы также можете объявить его следующим образом:
Observable<Response<MyResponseObject>> apiCall(@Body body);
Затем у вас есть подписчик, как показано ниже:
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!
}
}
Итак, ответы сервера с кодом ошибки также будут доставлены в onNext
, и вы можете получить код, вызвав reponse.code()
.
http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html
РЕДАКТИРОВАТЬ: ОК, я, наконец, добрался до того, что e-nouri сказал в своем комментарии, а именно, что только коды 2xx будут в onNext
. Оказывается, мы оба правы:
Если вызов объявлен следующим образом:
Observable<Response<MyResponseObject>> apiCall(@Body body);
или даже это
Observable<Response<ResponseBody>> apiCall(@Body body);
все ответы окажутся в onNext
, независимо от их кода ошибки. Это возможно, потому что все обернуто в объект Response
с помощью Retrofit.
Если, с другой стороны, вызов объявляется следующим образом:
Observable<MyResponseObject> apiCall(@Body body);
или
Observable<ResponseBody> apiCall(@Body body);
действительно, только ответы 2xx будут отправляться на onNext
. Все остальное будет завернуто в HttpException
и отправлено на onError
. Что также имеет смысл, потому что без оболочки Response
, что должно быть испущено на onNext
? Учитывая, что запрос не увенчался успехом, единственная разумная вещь, которую следует испустить, будет null
...