Zamiast deklarować wywołanie API, tak jak to zrobiłeś:
Observable<MyResponseObject> apiCall(@Body body);
Możesz również zadeklarować to w ten sposób:
Observable<Response<MyResponseObject>> apiCall(@Body body);
Będziesz mieć subskrybenta, takiego jak następujący:
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!
}
}
Tak więc odpowiedzi serwera z kodem błędu również zostaną dostarczone do onNext
i możesz uzyskać kod, dzwoniąc reponse.code()
.
http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html
EDYCJA: OK, w końcu zajrzałem do tego, co powiedział e-nouri w swoim komentarzu, a mianowicie, że tylko kody 2xx będą onNext
. Okazuje się, że oboje mamy rację:
Jeśli wywołanie jest zadeklarowane w następujący sposób:
Observable<Response<MyResponseObject>> apiCall(@Body body);
a nawet to
Observable<Response<ResponseBody>> apiCall(@Body body);
wszystkie odpowiedzi zakończą się onNext
, niezależnie od kodu błędu. Jest to możliwe, ponieważ Response
dzięki Retrofitowi wszystko jest opakowane w obiekt.
Jeśli, z drugiej strony, wezwanie zostanie zadeklarowane w następujący sposób:
Observable<MyResponseObject> apiCall(@Body body);
albo to
Observable<ResponseBody> apiCall(@Body body);
w rzeczywistości tylko odpowiedzi 2xx trafią do onNext
. Wszystko inne zostanie zapakowane HttpException
i wysłane na adres onError
. Co też ma sens, ponieważ bez Response
opakowania, do czego powinno być emitowane onNext
? Biorąc pod uwagę, że żądanie się nie powiodło, jedyną rozsądną rzeczą do wyemitowania byłoby null
...
onNext
tym 404 itd. Użyłem Retrofit v2.0.0-beta3.GsonConverterFactory
, tak jakRetrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
, jak uzyskać oryginalną odpowiedź?Response
. Rzadko go też używam - ale myślę, że dobrze jest wiedzieć, że istnieje.Wewnątrz metody onError umieść to, aby pobrać kod
źródło
HttpException
. Używam RxJava i musiałem przeanalizować odpowiedź po otrzymaniu plikuHTTP 400 BAD REQUEST
. Dziękuję Ci bardzo!Należy pamiętać, że od Retrofit2 wszystkie odpowiedzi z kodem 2xx zostanie wywołana z onNext () callback a resztą HTTP kody jak 4xx, 5xx będzie nazwany na onError () zwrotnego, wykorzystując Kotlin Mam wymyślił coś podobnego to w onError () :
źródło