背景及问题
在使用Okhttp
时,经常会用到自定义的拦截器,对请求体Request
或返回体Response
做额外的处理。
在拦截器中,通常使用如下方式获取Request
和Response
;
Request request = chain.request();//获取请求
Response response = chain.proceed(request);//处理请求,获取响应体
在处理Response
时,通常会对Response
中的返回体内容进行日志输出或者是内容判断等。为了获取请求体中的内容通常使用string()
函数获取;
Response response = chain.proceed(request);
String bodyStr = response.body().string();
在通过string()
函数获取返回体中的字符串以后,当我们尝试用同一个Response
对象再次使用string()
函数获取返回体的内容时,此时获取的内容返回为空字符串。
string()
在string()
函数被调用后,Response
返回体body()
中的所有字节都会被移除,其源码如下:
//:ResponseBody.java
public final String string() throws IOException {
BufferedSource source = this.source();
String var3;
try {
Charset charset = Util.bomAwareCharset(source, this.charset());
var3 = source.readString(charset);
} finally {
Util.closeQuietly(source);
}
return var3;
}
//:BufferedSource.java
/** Removes all bytes from this, decodes them as {@code charset}, and returns the string. */
String readString(Charset charset) throws IOException;
解决方法
在掉用string()
后,使用返回体的String
等信息重新创建新的Response
对象;
private Response login(Response response) {
try {
Response.Builder builder = response.newBuilder();
Response clone = builder.build();
ResponseBody body = clone.body();
if (body != null) {
MediaType mediaType = body.contentType();
if (mediaType != null) {
if (isText(mediaType)) {
String resp = body.string();
XLog.d(resp);//在这里输出请求体内容
//创建新的response
body = ResponseBody.create(mediaType, resp);
//在调用完string()后只有body()的内容清空,所以可以借助newBuilder手动添加body()来新建一个Response对象,对外部而言这两个response是没有区别的
return response.newBuilder()
.body(body)
.build();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}