OkHttp请求回调中response.body().string()只能有效调用一次

OkHttp请求回调中response.body().string()只能有效调用一次,为什么呢?
  • reponse.body()只能被调用一次?
  • reponse.body().string()只能被调用一次!
一、reponse.body()只能被调用一次?

很多人以为reponse.body()只能被调用一次,其实不然。

请看Okhttp源码中的Response.java文件的body()实现。

  /**
   * Returns a non-null value if this response was passed to {@link Callback#onResponse} or returned
   * from {@link Call#execute()}. Response bodies must be {@linkplain ResponseBody closed} and may
   * be consumed only once.
   *
   * <p>This always returns null on responses returned from {@link #cacheResponse}, {@link
   * #networkResponse}, and {@link #priorResponse()}.
   */
  public ResponseBody body() {
    return body;
  }

很显然,body()只是简单的返回了ResponseBody。

body的定义如下:

final ResponseBody body;

看看body()方法的注释吧,也许能发现点什么?翻译为中文如下:

    /**
     * 返回一个非空的值,如果这个反应是通过回调方法onResponse()或execute()方法返回。
     * 响应体必须关闭,并且可能只能消耗一次。
     * 如果响应体来自cacheresponse,networkresponse,priorresponse(),body()方法将总是返回null
     */

可以看到,这里只是告诉你响应体必须被关闭,但是这里并没有做这个操作。

它告诉你响应体可能只能被消耗一次,大概是因为响应体被消耗一次后必须关闭吧。

二、reponse.body().string()只能被调用一次!

为什么说,reponse.body().string()只能被调用一次!

请看Okhttp源码中的ResponseBody.java文件的string()实现。

  /**
   * 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 in
   * accordance to <a href="https://en.wikipedia.org/wiki/Byte_order_mark">its BOM</a> or UTF-8.
   * Closes {@link ResponseBody} automatically.
   *
   * <p>This method loads entire response body into memory. If the response body is very large this
   * may trigger an {@link OutOfMemoryError}. Prefer to stream the response body if this is a
   * possibility for your response.
   */
  public final String string() throws IOException {
    BufferedSource source = source();
    try {
      Charset charset = Util.bomAwareCharset(source, charset());
      return source.readString(charset);
    } finally {
      Util.closeQuietly(source);
    }
  }

可以看到执行完string()方法后,IO流必须被关闭。

Util.closeQuietly(source);

由此可知,string()方法只能调用一次,调用一次后响应体就失效了。

Closes {@link ResponseBody} automatically.

另外,由注释可知,string()方法会根据header中Content-Type返回对应编码的字符串,如果没有该属性则返回BOM或者UTF-8编码的字符串

再者,由注释可知,string()方法会把响应体的内容加载在内存中,如果响应体内容非常大,将会引发OutOfMemoryError异常,因此最好用流的方式去获取响应体。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值