OKHttp中的ResponseBody.string()方法
异常内容如下:IllegalStateException
java.lang.IllegalStateException: closed
at com.squareup.okhttp.internal.http.HttpConnection$FixedLengthSource.read(HttpConnection.java:455)
at okio.Buffer.writeAll(Buffer.java:594)
at okio.RealBufferedSource.readByteArray(RealBufferedSource.java:87)
at com.squareup.okhttp.ResponseBody.bytes(ResponseBody.java:56)
at com.squareup.okhttp.ResponseBody.string(ResponseBody.java:82)
或者出现OutOfMemory异常
如果采用ResponseBody的string()方法会一次性把数据读取到内存中,如果数据超过1MB可能会报内存溢出,所以对于超过1MB的数据,建议采用流的方式去读取,如ResponseBody的byteStream()方法。
解决方法
:
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String bodyInfo = "";
try {
ResponseBody body = response.body();
bodyInfo = inputStream2String(body.byteStream());
body.close();
} catch (Exception e) {
e.printStackTrace();
}
Log.d("--HttpClient", "--body:"+bodyInfo);
callback.onResponse(bodyInfo);
} else {
callback.onFailure(response.code());
}
}
public String inputStream2String(InputStream in) throws IOException {
StringBuffer out = new StringBuffer();
byte[] b = new byte[4096];
for (int n; (n = in.read(b)) != -1;) {
out.append(new String(b, 0, n));
}
return out.toString();
}
采用inputStream流的方式读取数据,这样可以避免直接调用string方法引起的OOM异常。
也可避免多次调用string方法引起的IllegalStateException异常。
注意
若onResponse中返回的内容过大,如3万条通讯录的信息,那么虽然通过inputStream读取可以有效避免OOM异常,但是在利用String转Json时,还是容易发生OOM异常,此时的解决方法应该是同服务器方一起修改;数据分批返回,如先返回总条数以及当前的条数,客户端按页来解析,解析完一页则做相应的存储,然后在内存中释放掉该页所占内存,当所有的信息均解析存储完毕,则认为此次任务完成,否则认为此次任务失败。