Exception:OkHttp Dispatcher
2017-12-05 本文已影响0人
OkCoco
项目中偶遇异常:
image.png
以下是异常代码片段:
@Override
public void onResponse(Response response) throws IOException {
...
Log.d("", "onResponse: "+response.body().string());
String responseContent = response.body().string();
...
}
异常定位到第二句代码,查看源码:
将按照请求头Content-Type属性规定的编码格式进对Response行解码,默认为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;
}
OkHttp的底层封装了Okio,Source在Okio中相当于InputStream。finally语句中调用了 Util.closeQuietly(source);,相当于把输入流给关闭了。第二次调用string()方法,由上面日志可知,最终会执行到HttpConnection$FixedLengthSource的read()方法,真正实现如下:
public long read(Buffer sink, long byteCount) throws IOException {
if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount);
if (closed) throw new IllegalStateException("closed");
if (bytesRemaining == 0) return -1;
long read = source.read(sink, Math.min(bytesRemaining, byteCount));
if (read == -1) {
unexpectedEndOfInput(); // The server didn't supply the promised content length.
throw new ProtocolException("unexpected end of stream");
}
bytesRemaining -= read;
if (bytesRemaining == 0) {
endOfInput(true);
}
return read;
}
最终的异常为这句代码输出:
if (closed) throw new IllegalStateException("closed");
结论
使用OkHttp时,不能接连调用两次Response的string()方法。
在一些第三方库中,同样会有自己的一些细节上的实现,多踩坑,多学习。