Retrofit 用response.body().string
2017-08-21 本文已影响0人
仁昌居士
Retrofit 或者是OkHttp用response.body().string()的方式输出日志注意事项
当我想有时候想打印请求回调数据时,会通过response.body().string()或者responseBody.string()的方式获取json数据字符串。这个就有注意的问题了。
注意事项:
先举个例子:
Log.d("rcjs",response.body().string());
和
Log.d("rcjs",responseBody.string());
这个都没问题,但是,
Log.d("rcjs",responseBody.string());
Log.d("rcjs",response.body().string());
这样就会GG了。
这是为什么呢?
单独使用这句并不会有问题。
因为,OkHttp不把它存储在内存中,就是你需要的时候就去读一次 只给你了内容,没有给引用,所以一次请求读一次,打印body后原ResponseBody会被清空,response中的流会被关闭,程序会报错,我们需要创建出一个新的ResponseBody 给应用层处理。
原理解析:
/**
* Returns the response as a string decoded with the charset of the Content-Type header. If that
* header is either absent or lacks a charset, this will attempt to decode the response body as
* UTF-8.
*/
public final String string() throws IOException {
return new String(bytes(), charset().name());
}
再往里走
public final byte[] bytes() throws IOException {
long contentLength = contentLength();
if (contentLength > Integer.MAX_VALUE) {
throw new IOException("Cannot buffer entire body for content length: " + contentLength);
}
BufferedSource source = source();
byte[] bytes;
try {
bytes = source.readByteArray();
} finally {
Util.closeQuietly(source);
}
if (contentLength != -1 && contentLength != bytes.length) {
throw new IOException("Content-Length and stream length disagree");
}
return bytes;
}
可以看出,执行了closeQuietly方法关闭资源操作。
Util.closeQuietly(source);
想要打印并能以后继续使用response的解决方法:
1.去新创建一个ResponseBody 去读取,response本身不进行读取操作
ResponseBody responseBody = response.peekBody(1024 * 1024);//关键代码
Log.d("REQUEST_JSON", responseBody.string());
这种方式有缺陷,当header的content-length不确定的情况下会出错,所以设置默认大小为1024*1024。
2.通过responseBody,去新建一个Response ,再用Response 其去打印
ResponseBody responseBody= ResponseBody.create(contentType, bodyString);//先决条件,有responseBody
Response responseNew = response.newBuilder().body(responseBody).build();//关键代码
Log.d("REQUEST_JSON", responseNew.body.string());
3.以Buffer的方式去读取显示。
ResponseBody responseBody = response.body();
BufferedSource source = responseBody.source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
Buffer buffer = source.buffer();
Charset UTF8 = Charset.forName("UTF-8");
Log.d("REQUEST_JSON", buffer.clone().readString(UTF8));
以上三种读取打印方式,我倾向后两者。