【问题标题】:Get response status code using Retrofit 2.0 and RxJava使用 Retrofit 2.0 和 RxJava 获取响应状态码
【发布时间】:2016-02-19 21:16:42
【问题描述】:

我正在尝试升级到 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 中做到这一点?

【问题讨论】:

    标签: android retrofit rx-java android-networking rx-android


    【解决方案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 结尾,无论其错误代码如何。这是可能的,因为所有东西都被 Retrofit 封装在 Response 对象中。

    另一方面,如果调用是这样声明的:

    Observable<MyResponseObject> apiCall(@Body body);
    

    或者这个

    Observable<ResponseBody> apiCall(@Body body);
    

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

    【讨论】:

    • 对于寻找 HTTP 代码 4xx 的人,他们最终会在 onError 中显示为 HttpException。 onNext 将只有 2xx。
    • 这很有趣...我刚刚再次检查 (gist.github.com/DavidMihola/17a6ea373b9312fb723b),我尝试的所有代码都以 onNext 结尾,包括 404 等。我使用了 Retrofit v2.0.0-beta3。跨度>
    • @e-nouri:我刚刚在我的回答中添加了一段,将您的评论考虑在内!
    • @david.mihola 如果 Build Retrofit via add GsonConverterFactory,就像Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()),如何得到原始响应?
    • 除了错误处理之外,我认为您可能希望能够检查与正文一起出现的任何响应标头 - 这也只有在您获得 Response 时才有可能。我也很少使用它——但我认为知道它确实存在是件好事。
    【解决方案2】:

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

    ((HttpException) e).code()
    

    【讨论】:

    • 这可能是我在 SO 中见过的最被低估的答案之一。这是天才。您可以使用HttpException 对响应执行您可能需要做的所有事情。我正在使用 RxJava,我需要在收到 HTTP 400 BAD REQUEST 后解析响应。非常感谢!
    • 之前一定要检查它是否是HttpException的实例,因为NetworkErrors将是IOExceptions并且没有状态码。
    • 接着@BenjaminMesing 谈到NetworkError,如果您在订阅之前在您的Rx 中执行更多下游操作符(map / flatMap / forEach 等),那么可能会有很多异常类型,不一定是网络请求上的错误。
    • java.lang.ClassCastException: java.lang.Throwable 无法转换为 retrofit2.HttpException
    【解决方案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))
      }
    

    【讨论】:

      猜你喜欢
      • 2018-02-27
      • 1970-01-01
      • 2016-09-02
      • 1970-01-01
      • 2016-12-15
      • 1970-01-01
      • 2019-08-23
      • 2016-10-28
      • 2018-10-08
      相关资源
      最近更新 更多