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));

以上三种读取打印方式,我倾向后两者。

上一篇下一篇

猜你喜欢

热点阅读