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。
我一直在尝试实现拦截器 (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。