使用Retrofit 2.0和RxJava获取响应状态代码

时间:2022-01-03 00:13:24

I'm trying to upgrade to Retrofit 2.0 and add RxJava in my android project. I'm making an api call and want to retrieve the error code in case of an error response from the server.

我正在尝试升级到Retrofit 2.0并在我的android项目中添加RxJava。我正在进行api调用,并希望在服务器发出错误响应的情况下检索错误代码。

Observable<MyResponseObject> apiCall(@Body body);

And in the RxJava call:

并在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
        }
    });

In Retrofit 1.9, the RetrofitError still existed and we could get the status by doing:

在Retrofit 1.9中,RetrofitError仍然存在,我们可以通过以下方式获得状态:

error.getResponse().getStatus()

How do you do this with Retrofit 2.0 using RxJava?

如何使用RxJava进行Retrofit 2.0?

3 个解决方案

#1


137  

Instead of declaring the API call like you did:

而不是像你一样声明API调用:

Observable<MyResponseObject> apiCall(@Body body);

You can also declare it like this:

您也可以这样声明:

Observable<Response<MyResponseObject>> apiCall(@Body body);

You will then have a Subscriber like the following:

然后,您将拥有如下所示的订阅者:

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

So, server responses with an error code will also be delivered to onNext and you can get the code by calling reponse.code().

因此,带有错误代码的服务器响应也将传递给onNext,您可以通过调用reponse.code()来获取代码。

http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html

http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html

EDIT: OK, I finally got around to looking into what e-nouri said in their comment, namely that only 2xx codes will to to onNext. Turns out we are both right:

编辑:好的,我终于开始研究e-nouri在他们的评论中所说的内容,即只有2xx代码才能进入onNext。事实证明我们都是对的:

If the call is declared like this:

如果调用声明如下:

Observable<Response<MyResponseObject>> apiCall(@Body body);

or even this

甚至这个

Observable<Response<ResponseBody>> apiCall(@Body body);

all responses will end up in onNext, regardless of their error code. This is possible because everything is wrapped in a Response object by Retrofit.

无论错误代码如何,所有响应都将以onNext结尾。这是可能的,因为Retrofit将所有内容包装在Response对象中。

If, on the other hand, the call is declared like this:

另一方面,如果调用声明如下:

Observable<MyResponseObject> apiCall(@Body body);

or this

或这个

Observable<ResponseBody> apiCall(@Body body);

indeed only the 2xx responses will go to onNext. Everything else will be wrapped in an HttpException and sent to onError. Which also makes sense, because without the Response wrapper, what should be emitted to onNext? Given that the request was not successful the only sensible thing to emit would be null...

实际上只有2xx的回复会转到onNext。其他所有内容都将包装在HttpException中并发送给onError。这也是有道理的,因为没有Response包装器,应该向onNext发出什么?鉴于请求不成功,发出的唯一合理的事情是null ...

#2


61  

Inside onError method put to this get the code

在onError方法里面放到这个获取代码

((HttpException) e).code()

#3


0  

You should note that as of Retrofit2 all responses with code 2xx will be called from onNext() callback and the rest of HTTP codes like 4xx, 5xx will be called on the onError() callback, using Kotlin I've came up with something like this in the onError() :

你应该注意到,从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))
  }

#1


137  

Instead of declaring the API call like you did:

而不是像你一样声明API调用:

Observable<MyResponseObject> apiCall(@Body body);

You can also declare it like this:

您也可以这样声明:

Observable<Response<MyResponseObject>> apiCall(@Body body);

You will then have a Subscriber like the following:

然后,您将拥有如下所示的订阅者:

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

So, server responses with an error code will also be delivered to onNext and you can get the code by calling reponse.code().

因此,带有错误代码的服务器响应也将传递给onNext,您可以通过调用reponse.code()来获取代码。

http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html

http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html

EDIT: OK, I finally got around to looking into what e-nouri said in their comment, namely that only 2xx codes will to to onNext. Turns out we are both right:

编辑:好的,我终于开始研究e-nouri在他们的评论中所说的内容,即只有2xx代码才能进入onNext。事实证明我们都是对的:

If the call is declared like this:

如果调用声明如下:

Observable<Response<MyResponseObject>> apiCall(@Body body);

or even this

甚至这个

Observable<Response<ResponseBody>> apiCall(@Body body);

all responses will end up in onNext, regardless of their error code. This is possible because everything is wrapped in a Response object by Retrofit.

无论错误代码如何,所有响应都将以onNext结尾。这是可能的,因为Retrofit将所有内容包装在Response对象中。

If, on the other hand, the call is declared like this:

另一方面,如果调用声明如下:

Observable<MyResponseObject> apiCall(@Body body);

or this

或这个

Observable<ResponseBody> apiCall(@Body body);

indeed only the 2xx responses will go to onNext. Everything else will be wrapped in an HttpException and sent to onError. Which also makes sense, because without the Response wrapper, what should be emitted to onNext? Given that the request was not successful the only sensible thing to emit would be null...

实际上只有2xx的回复会转到onNext。其他所有内容都将包装在HttpException中并发送给onError。这也是有道理的,因为没有Response包装器,应该向onNext发出什么?鉴于请求不成功,发出的唯一合理的事情是null ...

#2


61  

Inside onError method put to this get the code

在onError方法里面放到这个获取代码

((HttpException) e).code()

#3


0  

You should note that as of Retrofit2 all responses with code 2xx will be called from onNext() callback and the rest of HTTP codes like 4xx, 5xx will be called on the onError() callback, using Kotlin I've came up with something like this in the onError() :

你应该注意到,从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))
  }