Android异常:ResponseBody.string()导致的OutofMemory、IllegalStateException异常

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异常,此时的解决方法应该是同服务器方一起修改;数据分批返回,如先返回总条数以及当前的条数,客户端按页来解析,解析完一页则做相应的存储,然后在内存中释放掉该页所占内存,当所有的信息均解析存储完毕,则认为此次任务完成,否则认为此次任务失败。

这个错误通常发生在尝试将一个对象反序列化为`java.lang.String`或`java.util.ArrayList`时,但实际上收到的是一个`START_OBJECT`标记这意味着接收到的数据不是预期的字符串或数组格式。 解决这个问题的方法是检查接口返回的数据是否与你的预期相符。可能有以下几种情况导致这个错误: 1. 返回的数据类型与你的预期不符:检查接口文档或与后端开发人员确认接口返回的数据类型是否为字符串或数组。如果不是,你需要相应地调整你的代码来处理正确的数据类型。 2. 数据格式错误:检查接口返回的数据是否符合你的预期格式。例如,如果你期望一个字符串,但实际上返回的是一个对象或数组,那么你需要相应地处理这种情况。 3. 数据为空:如果接口返回的数据为空,那么你需要在代码中进行相应的处理,以避免出现反序列化错误。 以下是一个示例代码,用于处理接口返回的数据并避免出现反序列化错误: ```java // 假设接口返回的数据是一个对象 Response response = // 发送接口请求并获取响应 if (response.isSuccessful()) { String responseBody = response.body().string(); // 检查数据是否为空 if (responseBody != null && !responseBody.isEmpty()) { // 尝试将数据反序列化为字符串 try { String result = new Gson().fromJson(responseBody, String.class); // 处理字符串数据 } catch (JsonSyntaxException e) { // 数据格式错误,处理异常情况 } } else { // 数据为空,处理异常情况 } } else { // 处理接口请求失败的情况 } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值