Android开发:如何在Retrofit响应中保留errorBody()内容?
这个问题我之前在做Retrofit接口请求的时候踩过坑!核心原因是Retrofit返回的ResponseBody(包括errorBody()拿到的实例)本质是一个一次性的输入流,一旦你调用string()或者byteStream()读取过一次,流就会被关闭,后续再调用就会返回null。
要解决这个问题,关键是提前把errorBody的内容备份到内存里,这样就能在不同场景下多次使用而不依赖原流。这里给你两种实用的方案:
方案1:用Okio备份(推荐,Retrofit自带依赖)
Retrofit底层基于Okio实现,所以不需要额外引入依赖,直接用Okio的source()把整个响应体读取成字节数组,之后就可以随意转换为字符串或者重建ResponseBody:
Kotlin示例:
val errorBody = response.errorBody() ?: return // 读取所有字节到内存 val errorBytes = errorBody.source().readByteArray() // 第一次获取错误信息 val errorMsg1 = String(errorBytes, Charsets.UTF_8) // 其他场景再次获取 val errorMsg2 = String(errorBytes, Charsets.UTF_8) // 如果需要还能重建一个可复用的ResponseBody val reusableErrorBody = ResponseBody.create(errorBody.contentType(), errorBytes)
Java示例:
ResponseBody errorBody = response.errorBody(); if (errorBody == null) { return; } // 读取字节数组 byte[] errorBytes = errorBody.source().readByteArray(); // 多次使用错误信息 String errorMsg1 = new String(errorBytes, StandardCharsets.UTF_8); String errorMsg2 = new String(errorBytes, StandardCharsets.UTF_8); // 重建ResponseBody用于后续逻辑 ResponseBody reusableErrorBody = ResponseBody.create(errorBody.contentType(), errorBytes);
方案2:用传统IO流备份
如果不想用Okio,也可以用Java标准的InputStream来读取并备份:
ResponseBody errorBody = response.errorBody(); if (errorBody == null) { return; } // 用try-with-resources自动关闭流,避免内存泄漏 try (InputStream inputStream = errorBody.byteStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { byte[] buffer = new byte[1024]; int readLength; while ((readLength = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, readLength); } // 备份的字节数组 byte[] errorBytes = outputStream.toByteArray(); // 后续多次使用错误信息 String errorMsg1 = new String(errorBytes, StandardCharsets.UTF_8); String errorMsg2 = new String(errorBytes, StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); }
注意事项
- 不要试图直接保存原
ResponseBody实例,因为它的流只能读取一次 - 如果错误响应体特别大,要考虑内存占用,但一般错误信息都是简短的JSON或文本,不会有问题
- 不管用哪种方案,核心都是把流的内容提前复制到内存(字节数组),这样就能脱离原流多次访问
内容的提问来源于stack exchange,提问作者Teszt Cell
相关产品推荐
相关产品推荐

