Android Retrofit 2,addInterceptor 和 addNetworkInterceptor 编辑响应的区别

Android Retrofit 2, differences between addInterceptor & addNetworkInterceptor for editing responses

我一直在尝试实现拦截器 (OkHttp 3.2 和 Retrofit 2) 以编辑 JSON 响应,然后 returned 作为响应.我们请求数据的服务器 return 不同的数据取决于成功或错误,这使得映射对象变得困难。

我试图通过将拦截器作为 NetworkInterceptor 添加到 Retrofit 来实现,但是字符串 returned 没有格式。

@Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        Response response = chain.proceed(request);
        try {

            final String responseString = new String(response.body().bytes() ); 

            LOGD("OkHttp-NET-Interceptor", "Response: " + responseString);

            String  newResponseString = editResponse( responseString );

            LOGD("OkHttp-NET-Interceptor", "Response edited: " + newResponseString);
            return  response.newBuilder()
                    .body(ResponseBody.create(response.body().contentType(), newResponseString))
                    .build();

        }catch (Exception ex){
            return response;
        }
    }

responseString 有一个没有任何可理解格式的字符串。

更改为普通拦截器后,字符串具有能够转换为 JSONObject.

的格式

谁能告诉我响应之间的区别是什么?

为什么这一行 new String(response.body().bytes() ); return 内容不同?

区别在于名称。 NetworkInterceptor 在网络级别挂钩,是放置重试逻辑和任何不依赖于响应的实际内容的理想位置。

如果你做什么取决于响应的内容(就像你的情况),使用 ApplicationInterceptor 更有用,因为它会在你的任何其他移动部件处理后为你提供响应可能有 JSON 反序列化器。否则,您将不得不在 NetworkInterceptor 中实现 JSON 反序列化,考虑到 Retrofit 已为您完成,这没有多大意义。

澄清

Square 在他们的 wiki 上有这张有用的图表,显示了每种类型的拦截器所在的位置

因此,您在 ApplicationInterceptor 中收到可读字符串的原因是因为 Square 正试图 de-couple 两种拦截器类型的目的。他们认为您不应该在 NetworkInterceptor 中做出任何依赖于应用程序的决定,因此他们没有为您提供访问响应字符串的简单方法。有可能得到,但就像我说的,他们不希望您根据响应的内容做出决定 - 相反,他们希望您根据网络状态或 headers等

ApplicationInterceptor 他们希望您根据响应的内容做出决定,因此他们提供了更简单的方法来访问响应的内容,以便您可以做出重试的明智决定,或者正如他们在他们的 wiki 中详细介绍的那样,rewrite responses(我相信这就是您正在尝试做的)。

根据@square:

每个拦截器链都有相对优点。

应用程序拦截器

  • 无需担心重定向和重试等中间响应。

  • 总是被调用一次,即使 HTTP 响应是从缓存中提供的。

  • 观察申请的初衷。不关心 OkHttp-injected headers 喜欢 If-None-Match.

  • 允许 short-circuit 而不是调用 Chain.proceed()。

  • 允许重试并多次调用 Chain.proceed()。

  • 可以使用 withConnectTimeout、withReadTimeout、withWriteTimeout 调整调用超时。

网络拦截器

  • 能够对重定向和重试等中间响应进行操作。
  • 不为 short-circuit 网络的缓存响应调用。
  • 在数据将通过网络传输时观察数据。
  • 访问承载请求的Connection。