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

我正在尝试升级到Retrofit 2.0,并在我的Android项目中添加RxJava。 我正在做一个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 } }); 

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

 error.getResponse().getStatus() 

如何使用RxJava进行Retrofit 2.0操作?

而不是像你所做的那样声明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, eg UnknownHostException, will end up here } @Override public void onNext(Response<StartupResponse> startupResponseResponse) { Timber.d("onNext: %s", startupResponseResponse.code()); // HTTP errors, eg 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结束。 这是可能的,因为所有东西都通过Retrofit包装在Response对象中。

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

 Observable<MyResponseObject> apiCall(@Body body); 

或这个

 Observable<ResponseBody> apiCall(@Body body); 

事实上,只有2xx的回应将onNext 。 其他一切都将被包装在一个HttpException ,并发送到onError 。 这也是有道理的,因为没有Response包装, 应该发射到onNext ? 鉴于请求不成功,唯一明智的事情发出将是null

里面的onError方法把这个得到的代码

 ((HttpException) e).code() 

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