我正在尝试升级到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
}
});
在Retrofit 1.9中,RetrofitError仍然存在,我们可以通过以下方式获得状态:
error.getResponse().getStatus()
如何使用RxJava进行Retrofit 2.0?
答案 0 :(得分:169)
而不是像你那样声明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
结尾。这是可能的,因为Retrofit将所有内容都包装在Response
对象中。
另一方面,如果呼叫声明如下:
Observable<MyResponseObject> apiCall(@Body body);
或者
Observable<ResponseBody> apiCall(@Body body);
实际上只有2xx的回复会转到onNext
。其他所有内容都将包含在HttpException
中并发送给onError
。这也是有道理的,因为没有Response
包装器,应该发送到onNext
?鉴于请求不成功,发出的唯一合理的事情是null
...
答案 1 :(得分:91)
在onError中放入此方法获取代码
((HttpException) e).code()
答案 2 :(得分:7)
您应该注意,从 Retrofit2 开始,代码 2xx 的所有响应都将从onNext()回调调用,其余 HTTP代码比如4xx,将在 onError()回调中调用5xx,使用 Kotlin 我在 onError()<中提出了类似的内容/ strong>:
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))
}