Retrofit 自定义GsonConverterFactory 解析异常

在用自定义GsonConverterFactory 中解析数据出现异常

retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall@5c86aee==java.lang.IllegalStateException: closed===closed```

完整如下:

java.lang.IllegalStateException: closed
at okio.RealBufferedSource.read(RealBufferedSource.java:44)
at okio.ForwardingSource.read(ForwardingSource.java:35)
at retrofit2.OkHttpCall$ExceptionCatchingRequestBody$1.read(OkHttpCall.java:290)
at okio.RealBufferedSource.request(RealBufferedSource.java:68)
at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:418)
at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:402)
at okhttp3.internal.Util.bomAwareCharset(Util.java:432)
at okhttp3.ResponseBody$BomAwareReader.read(ResponseBody.java:249)
at com.google.gson.stream.JsonReader.fillBuffer(JsonReader.java:1295)
at com.google.gson.stream.JsonReader.nextNonWhitespace(JsonReader.java:1333)
at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:549)
at com.google.gson.stream.JsonReader.peek(JsonReader.java:425)

开始怀疑是数据实体类没有写对,经过确认,实体类并没毛病,查询其它博客发现,在

@Override
public T convert(ResponseBody value) throws IOException {
  try {.. }
}

对value (ResponseBody)只能读取一次 , 如果你调用了response.body().string()两次或者response.body().charStream()两次就会出现这个异常, 先调用string()再调用charStream()也不可以.
查看ResponseBody源码描述,

* <p>Because this class does not buffer the full response in memory, the application may not
 * re-read the bytes of the response. Use this one shot to read the entire response into memory with
 * {@link #bytes()} or {@link #string()}. Or stream the response with either {@link #source()},
 * {@link #byteStream()}, or {@link #charStream()}.
 */
public abstract class ResponseBody implements Closeable {
  /** Multiple calls to {@link #charStream()} must return the same instance. */
  private Reader reader;

  public abstract @Nullable MediaType contentType();

因为ResponseBody类不会在内存中缓冲完整响应,所以应用程序可能不会 重新读取响应的字节

value值是一次性的,而在自定义GsonConverterFactory 中,我用了2次,第二次读取不到,造成异常的发生
解决办法:保存一个ResponseBody

@Override
    public T convert(ResponseBody value) throws IOException {
        String response = value.string();
        HttpStatus httpStatus = gson.fromJson(response, HttpStatus.class);
        if (httpStatus.isCodeInvalid()) {
            value.close();
            throw new ApiException(httpStatus.getCode(), httpStatus.getMessage());
        }

        MediaType contentType = value.contentType();
        Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
        InputStream inputStream = new ByteArrayInputStream(response.getBytes());
        Reader reader = new InputStreamReader(inputStream, charset);
        JsonReader jsonReader = gson.newJsonReader(reader);

        try {
            return adapter.read(jsonReader);
        } finally {
            value.close();
        }
    }

参考文章
Retrofit自定义GsonConverter处理请求错误异常处理

猜你喜欢

转载自blog.csdn.net/K_Hello/article/details/81335788