Invece di dichiarare la chiamata API come hai fatto:
Observable<MyResponseObject> apiCall(@Body body);
Puoi anche dichiararlo in questo modo:
Observable<Response<MyResponseObject>> apiCall(@Body body);
Avrai quindi un abbonato come il seguente:
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!
}
}
Pertanto, verranno consegnate anche le risposte del server con un codice di errore onNext
e sarà possibile ottenere il codice chiamando reponse.code()
.
http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html
EDIT: OK, finalmente sono riuscito a esaminare cosa ha detto e-nouri nel loro commento, vale a dire che solo i codici 2xx lo faranno onNext
. Si scopre che abbiamo entrambi ragione:
Se la chiamata viene dichiarata in questo modo:
Observable<Response<MyResponseObject>> apiCall(@Body body);
o anche questo
Observable<Response<ResponseBody>> apiCall(@Body body);
tutte le risposte finiranno in onNext
, indipendentemente dal loro codice di errore. Questo è possibile perché tutto è avvolto in un Response
oggetto da Retrofit.
Se invece la chiamata viene dichiarata così:
Observable<MyResponseObject> apiCall(@Body body);
o questo
Observable<ResponseBody> apiCall(@Body body);
infatti solo le risposte 2xx andranno a onNext
. Tutto il resto verrà avvolto in un HttpException
e inviato a onError
. Il che ha anche senso, perché senza il Response
wrapper, cosa dovrebbe essere emesso onNext
? Dato che la richiesta non è andata a buon fine l'unica cosa sensata da emettere sarebbe null
...