Thay vì khai báo lệnh gọi API như bạn đã làm:
Observable<MyResponseObject> apiCall(@Body body);
Bạn cũng có thể khai báo nó như thế này:
Observable<Response<MyResponseObject>> apiCall(@Body body);
Sau đó, bạn sẽ có một Người đăng ký như sau:
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!
}
}
Vì vậy, phản hồi của máy chủ có mã lỗi cũng sẽ được gửi đến onNext
và bạn có thể lấy mã bằng cách gọi reponse.code()
.
http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html
CHỈNH SỬA: OK, cuối cùng tôi đã tìm hiểu xem e-nouri đã nói gì trong bình luận của họ, cụ thể là chỉ có mã 2xx onNext
. Hóa ra cả hai chúng ta đều đúng:
Nếu cuộc gọi được khai báo như thế này:
Observable<Response<MyResponseObject>> apiCall(@Body body);
hoặc thậm chí cái này
Observable<Response<ResponseBody>> apiCall(@Body body);
tất cả các phản hồi sẽ kết thúc onNext
, bất kể mã lỗi của chúng là gì. Điều này có thể thực hiện được vì mọi thứ đều được bọc trong một Response
đối tượng bởi Retrofit.
Mặt khác, nếu lệnh gọi được khai báo như thế này:
Observable<MyResponseObject> apiCall(@Body body);
hoặc cái này
Observable<ResponseBody> apiCall(@Body body);
thực sự chỉ có phản hồi 2xx onNext
. Mọi thứ khác sẽ được gói trong một HttpException
và gửi đến onError
. Điều này cũng có ý nghĩa, bởi vì không có Response
trình bao bọc, cái gì sẽ được phát ra onNext
? Cho rằng yêu cầu không thành công, điều hợp lý duy nhất để phát ra sẽ là null
...