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