OKHttp源码分析(三)之ResponseBody

OKHttp源码分析(三)之ResponseBody

2023年7月9日发(作者:)

OKHttp源码分析(三)之ResponseBody⼀,概述在使⽤OKHttp访问⽹络时,⽆论是同步请求还是异步请求,返回结果都是Response对象,所有的数据都封装在这个对象中。

这个对象常⽤的⽅法有:int code = ();//获取响应码String message = e();//获取响应消息ResponseBody body = ();//获取响应体InputStream inputStream = ream();//获取输⼊流byte[] bytes = ();//获取字节数组String str = ();//获取字符串数据响应码和响应消息很简单,这⾥不做介绍了,下⾯主要看response的body⽅法。response的body⽅法返回ResponseBody对象,从ResponseBody对象中可以获取到流,字节数组,字符串等类型的数据。下⾯重点讲解ResponseBody对象是如何创建的,是怎么从ResponseBody对象中获取到不同数据的。⼆,ResponseBody对象的创建看源码可知,ResponseBody类是⼀个抽象类,不能被实例化。⼀般使⽤它的⼦类RealResponseBody实例化对象。RealResponseBody类的构造⽅法 源码如下: public RealResponseBody(Headers headers, BufferedSource source) { s = headers; = source; }由此可知,在创建RealResponseBody对象时,传递了BufferedSource 对象,BufferedSource 是okio库中的输⼊流,这⾥就当作inputStream来使⽤。注意:这个BufferedSource 对象很重要,它是⽹络请求成功后返回的流对象,所有的数据都要从这个流中获取。在RealResponseBody类中字段source 是私有的,所以需要提供对外访问的公共⽅法,如下: @Override public BufferedSource source() { return source; }总结:在创建ResponseBody时,传递过来⼀个流对象。三,从ResponseBody中获取输⼊流对象从ResponseBody中获取输⼊流对象的代码是:InputStream inputStream = ream();//获取输⼊流ResponseBody类的byteStream⽅法的原码是: public final InputStream byteStream() { return source().inputStream(); }这个代码很简单,⾸先调⽤source⽅法返回BufferedSource 对象,BufferedSource 就是封装的inputStream,所以可以从,BufferedSource对象中获取inputStream对象。三,从ResponseBody中获取字节数组从ResponseBody中获取字节数组的代码是:byte[] bytes = ();//获取字节数组ResponseBody类的bytes⽅法的原码是: public final byte[] bytes() throws IOException { long contentLength = contentLength(); BufferedSource source = source(); byte[] bytes; try { bytes = teArray(); } finally { uietly(source); } return bytes; }源码中⾸先调⽤的是source⽅法,source⽅法返回BufferedSource 对象。然后调⽤BufferedSource 的readByteArray⽅法返回字节数组。四,从ResponseBody中获取字符串数据从ResponseBody中获取字符串数据的⽅法:String str = ();//获取字符串数据ResponseBody类的string⽅法的原码是: public final String string() throws IOException { return new String(bytes(), charset().name()); }这个⽅法⽐较简单,先调⽤bytes⽅法得到字节数组,再将字节数组转换为字符串。五,OKHttp中实现⽂件下载分析ResponseBody类的原码发现:OKHttp并没有提供下载⽂件放⽅法。在httpURLconnection中下载⽂件时是先得到输⼊流对象,然后从输⼊流对象中读取数据得到⽂件对象。在OKHttp中也能得到流对象,所以也可以⾃⼰实现⽂件下载,下载代码如下:try{ InputStream is = ().byteStream();//从服务器得到输⼊流对象 long sum = 0; File dir = new File(mDestFileDir); if (!()){ (); } File file = new File(dir, mdestFileName);//根据⽬录和⽂件名得到file对象 FileOutputStream fos = new FileOutputStream(file); byte[] buf = new byte[1024*8]; int len = 0; while ((len = (buf)) != -1){ (buf, 0, len); } (); return file;}五,注意要点从上⾯的分析可知,ResponseBody类的源码是⾮常简单的。本质就是从输⼊流中获取数据,但在初次使⽤时遇到了很多问题,现在总结如下:1. 在解析ResponseBody前ResponseBody中仅仅有流对象,调⽤string⽅法时才开始解析流对象,所以这⼀步操作仍然需要与服务器有联系,仍然属于访问服务器的范畴,所以必须放在⼦线程中。只有得到String对象后才能跳转到UI线程修改UI。2. 在解析ResponseBody前ResponseBody中仅仅有流对象,调⽤string⽅法就是从输⼊流中读取数据,这⾏代码执⾏完毕表⽰读取完毕。⽽此时再次调⽤string⽅法就得不到数据了。同理bytes⽅法也是从输⼊流中读取数据,所以调⽤string⽅法后再次调⽤bytes⽅法也得不到数据。3. 从ResponseBody的byteStream⽅法中得到inputstream对象时,并没有从输⼊流中读取数据,此时仍然可以从string⽅法中获取到数据。但是获取string数据后,inputstream对象仍存在,但⾥⾯已经没有数据了。

发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1688907350a182276.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信