在鸿蒙应用开发中使用OkHttp的时候出现了一个匪夷所思的Bug,错误提醒如下:
Device info:JAD-AL50
Build info:JAD-AL50 2.0.0.241(C00E230R3P4)
Module name:com.example.attendenceapplication
Version:1.0.0
Pid:4504
Uid:1011557
Foreground:Yes
Reason:IllegalStateException
Selected stacktrace:
java.lang.IllegalStateException: closed
at okio.RealBufferedSource.select(RealBufferedSource.java:93)
at okhttp3.internal.Util.bomAwareCharset(Util.java:467)
at okhttp3.ResponseBody.string(ResponseBody.java:181)
at com.example.attendenceapplication.slice.TakePhotoSlice$2.onResponse(TakePhotoSlice.java:224)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:174)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:929)
根据错误提醒可知Bug发生在代码的224行,如下:
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println("body is " +response.body().string());
ResultVO resultVO = gson.fromJson(response.body().string(),ResultVO.class);
System.out.println(resultVO.getCode());
System.out.println(resultVO.getMsg());
uiTaskDispatcher.asyncDispatch(() -> {
showTips(TakePhotoSlice.this, resultVO.getMsg());
if (resultVO.getMsg().trim().equals("人脸上传成功")){
terminateAbility();
}
});
}
});
onResponse是OkHttp的一个回调函数,其中Response response可以获取后端返回的数据包括headers、body等。第224行代码是将Response的body转换为对应的实体类,正是这一行代码导致了Bug的出现。根据错误提醒可知我应该是使用了一个已经关闭的数据流,但是我并没有关闭数据流啊,怎么回事。 经过一天一夜的折腾,我才知道为什么会报错了。 因为在 System.out.println("body is " +response.body().string());这一行代码中执行了response.body().string()方法,此方法不仅会把response的body转换为字符串,同时还会把数据流进行关闭,导致ResultVO resultVO = gson.fromJson(response.body().string(),ResultVO.class);转换不了实体类,简而言之就是使用了两次response.body().string()。 string()方法的源码如下:从源码可以看出在执行string()方法后就会执行 $closeResource(var2, source);方法,从而关闭了数据流。 解决办法就是将System.out.println("body is " +response.body().string());注释掉即可
public final String string() throws IOException {
BufferedSource source = this.source();
Throwable var2 = null;
String var4;
try {
Charset charset = Util.bomAwareCharset(source, this.charset());
var4 = source.readString(charset);
} catch (Throwable var8) {
var2 = var8;
throw var8;
} finally {
if (source != null) {
$closeResource(var2, source);
}
}
return var4;
}
|