OkHttp 报java.lang.IllegalStateException: closed

原因是.body.string()只能调用一次。再次调用就会抛if (closed) throw new IllegalStateException("closed");
分析:.body().string()
.body()创建一个ResponseBody对象

 public @Nullable ResponseBody body() {
    return body;
  }

.string()

public final String string() throws IOException {
    BufferedSource source = source();
    try {
      Charset charset = Util.bomAwareCharset(source, charset());
      return source.readString(charset);
    } finally {
      Util.closeQuietly(source);
    }
  }

创建一个缓冲区source
Charset是Unicode字符和字节序列之间的命名映射
看readString()方法,调用了RealBufferedSource的readString()

@Override public String readString(Charset charset) throws IOException {
    if (charset == null) throw new IllegalArgumentException("charset == null");
    buffer.writeAll(source);
    return buffer.readString(charset);
  }

看writeAll()方法

@Override public long writeAll(Source source) throws IOException {
    if (source == null) throw new IllegalArgumentException("source == null");
    long totalBytesRead = 0;
    for (long readCount; (readCount = source.read(this, Segment.SIZE)) != -1; ) {
      totalBytesRead += readCount;
    }
    return totalBytesRead;
  }

直接看for循环里面的source.read()方法,在RealBufferedSource类里面

 @Override public long read(Buffer sink, long byteCount) throws IOException {
    if (sink == null) throw new IllegalArgumentException("sink == null");
    if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount);
    if (closed) throw new IllegalStateException("closed");

    if (buffer.size == 0) {
      long read = source.read(buffer, Segment.SIZE);
      if (read == -1) return -1;
    }

    long toRead = Math.min(byteCount, buffer.size);
    return buffer.read(sink, toRead);
  }

可以看到if (closed) throw new IllegalStateException("closed");这里抛出的异常
closed

@Override public void close() throws IOException {
    if (closed) return;
    closed = true;
    source.close();
    buffer.clear();
  }

我们回到.string()方法,有个finally{}

  public final String string() throws IOException {
    BufferedSource source = source();
    try {
      Charset charset = Util.bomAwareCharset(source, charset());
      return source.readString(charset);
    } finally {
      Util.closeQuietly(source);
    }
  }

进入closeQuietly()方法

  public static void closeQuietly(Closeable closeable) {
    if (closeable != null) {
      try {
        closeable.close();
      } catch (RuntimeException rethrown) {
        throw rethrown;
      } catch (Exception ignored) {
      }
    }
  }

现在就很明显了,因为

finally {
      Util.closeQuietly(source);
    }

使的closed=true,所以在此调用string(),就会抛出异常
纯属个人观点,如有错误欢迎指正!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容