Подтвердить что ты не робот

Получить код состояния ответа с помощью Retrofit 2.0 и RxJava

Я пытаюсь перейти на Retrofit 2.0 и добавить RxJava в мой проект Android. Я делаю вызов api и хочу получить код ошибки в случае ответа на ошибку с сервера.

Observable<MyResponseObject> apiCall(@Body body);

И в вызове 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
        }
    });

В Retrofit 1.9 RetrofitError все еще существовал, и мы могли получить статус, выполнив:

error.getResponse().getStatus()

Как вы это делаете с помощью Retrofit 2.0 с помощью RxJava?

4b9b3361

Ответ 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...

Ответ 2

Внутри метода onError, поставленного на это, получите код

((HttpException) e).code()

Ответ 3

Следует отметить, что из Retrofit2 все ответы с кодом 2xx будут вызваны из обратного вызова onNext(), а остальные HTTP-коды как 4xx, 5xx будет вызван в обратном вызове onError(), используя Kotlin. Я придумал что-то вроде этого в onError():

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))
  }