【问题标题】:Retrofit rxJava does not invoke onError for 500 internal server errorsRetrofit rxJava 不会为 500 个内部服务器错误调用 onError
【发布时间】:2017-02-16 21:03:29
【问题描述】:

在 android 上,我通过改造进行服务器调用,服务器有时会返回 500 响应。

onError 没有在订阅者中被调用是否有原因?

            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Response<Void>>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
                    if (isViewAttached()) {
                        getView().onError(e);
                    }
                }

                @Override
                public void onNext(Response<Void> response) {
                    response.code() <-- why would 500 here not get routed to the onError instead?
                }
            });

【问题讨论】:

    标签: android retrofit2


    【解决方案1】:

    这部分取决于您的配置,部分取决于您定义呼叫的方式,但这一切都归结为 2 Observables 之一。

    如果您查看源代码,您会发现如果您的调用返回 Response&lt;Foo&gt; 类型,Retrofit 将在内部为您的调用创建 CallEnqueueObservable&lt;Foo&gt;CallExecuteObservable。在adapt 方法中查看。对于 RxJava 1,这是类似的,但 observables 的调用方式不同。无论如何,在内部,事情的运作方式是完全一样的。调用被执行,onNext 被一个response 实例调用。

    如果你看看它在Retrofit 的代理机制中是如何工作的,即使响应是一个 Http 错误,也总会有一个response 实例。这意味着即使响应本身是 http 错误,调用 onNext 仍然会发生。您可以查看parseReponse 方法,如果状态码为 500,则不会引发异常。

    回到 observables,只有当有异常时,订阅者的 onError 才会被调用。请记住,如果是状态码 500,则不会引发异常。

    要让您的 onError 触发非 2XX http 错误代码,有多种方法,但一种可能的方法是(如果您负担得起)让您的呼叫返回 Observable&lt;Foo&gt; 而不是 Observable&lt;Response&lt;Foo&gt;&gt;

    这将使改造在内部使用不同的可观察对象,确保在出现 http 错误和异常时调用订阅者的 onError

    【讨论】:

      【解决方案2】:

      只有网络错误会被抛出到onError(例如没有互联网连接)。

      将 500er 视为来自服务器的有效响应,而不是错误情况。此外,您想使用服务器提供的错误信息(正文、状态代码、标题等)。 onError 不能提供这个(除非作为例外)。

      【讨论】:

      • 我不明白的是,其他 API 调用中的 400 / 500 错误似乎被路由到了 onError。
      • 也许您没有用Response&lt;..&gt; 包装其他API 调用?如果没有响应包装所有错误将调用onError
      • 只是为了完成它:如果您将对象包装到 Result&lt;..&gt; 中,每个请求都会调用 onNext,即使出现网络错误。
      • 我使用了 retrofit-rxjava 适配器。所以确实被路由的那个看起来像 Observable doSomething();并且未路由的定义为 Observable> doSomeOtherThing();您是说“包装”还是改造客户端声明的返回类型决定是否在实际服务器错误时调用 onError?
      猜你喜欢
      • 2014-05-17
      • 1970-01-01
      • 1970-01-01
      • 2018-01-04
      • 2019-01-17
      • 2011-10-17
      • 2010-11-15
      • 1970-01-01
      相关资源
      最近更新 更多