Volley源码解析(二)
来源:互联网 发布:java web菜单权限控制 编辑:程序博客网 时间:2024/06/08 11:52
在Volley源码解析 (一)中简单的说明了volley的执行流程:从Request到生成NetWorkResponse的过程,本文就上篇博客的基础上继续讲解最后一步——>生成Response<>的过程(本篇的读者建议先大致看下《Volley 源码解析(一)》。
简单了解下Network Response:
NetworkResponse包含了网络返回的主要数据:比如原始数据的字节数组,服务器header信息等,代码如下:
/** http状态码. */ public final int statusCode; /** 服务器响应的原始数据 */ public final byte[] data; /** 响应http首部*/ public final Map<String, String> headers;
也就是说我们通过操作BasicNetwork返回的NetworkResponse来对原始数据进行处理;换句话说我们可以不通过volley提供的Response《String》,Response《JsonObject》,Response《JsonArray》等对象,而我们自己对原始数据进行转换和使用。
比如下面代码,发起一个请求,然后将数据转换成字符串:
//创建一个请求对象 StringRequest request = new StringRequest("http://www.baidu.com",null,null); //利用HurlStack创建一个BasicNetwork对象 BasicNetwork basicNetwork = new BasicNetwork(new HurlStack()); //发起请求,返回NetWorkResponse NetworkResponse networkResponse = basicNetwork.performRequest(request); //将原始数据转换成字符串 String str = new String(networkResponse.data); //对Str进行打印。输出结果如下:
通过上面几行代码我们就可以获取想要的字符串了,那么volley对是怎么获取String的呢?在StringRequest的基类Request提供了一个抽象方法:
//注意该方法返回的是Response对象 abstract protected Response<T> parseNetworkResponse(NetworkResponse response);
所以我们可以看看StringRequest类对此抽象方法的具体实现:
protected Response<String> parseNetworkResponse(NetworkResponse response) { String parsed; try { parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); }
代码很简单,也就是讲NetworkRespone的data和header转换成parsed 字符串,然后交给Response的success方法,最终返回一个Response《String》对象的过程:
public static <T> Response<T> success(T result, Cache.Entry cacheEntry) { //将处理的结果交给result来持有 return new Response<T>(result, cacheEntry); }
所以如果读者想简单了解ImageRequest的Bitmap是怎么生成的,就可以参看ImageRequest的parseNetworkResponse方法,同样的道理可以了解volley的JsonReqeust对象JsonObject构建原理,此处不在赘述。
我们可以通过Response的result来获取我们需要的数据对象Bitmap,JsonObject,String等。
简单对上文的说明做下总结,也是volley工作流程大致过程:
1、构建相应的Request对象
2、Volley使用BasicNetwork对象的performRequest(request)发起数据请求,获得NetworkResponse对象
3、将NetworkResponse交给Request的parseNetworkResponse方法,将networkResponse持有的原始数据data(byte[])转换成具体的对象:比如String、Bitmap、JsonObject等。
4、将步骤3生成对象数据交给Response对象的result对象持有,从而交给客户端使用。
不知道读者发现没有,到此为止,扯了这么多,博主使用没有说明上述的这些过程在Volley时怎么发起的!!!比如BasicNetwork的performRequest是什么时候调用的?parseNetworkResponse又是什么时候调用的,Response对象又是怎么交给客户端的呢?下面就来讲解下这部分。
通常一些耗时的操作都需要在线程中去处理,网络请求也不例外,Volley亦然!!Volley提供了一个NetworkDispatcher的线程类(Thread的子类),这个线程类的主要作用就是执行上面讲解的四个步骤!所以看看其run方法都做了些什么:
public void run() { while (true) {//一个while循环 Request<?> request; try { //从队列里获取一个请求 request = mQueue.take(); } catch (InterruptedException e) { if (mQuit) { return; } continue; } try { //如果客户端取消了请求,则调用请求回调接口通知客户端 if (request.isCanceled()) { request.notifyListenerResponseNotUsable(); //继续循环获取队列里的下一个请求 continue; } //执行BasicNetwork的performReqeust方法 NetworkResponse networkResponse = mNetwork.performRequest(request); //如果服务服返回304状态吗,并且我们已经将请求交付给客户端 if (networkResponse.notModified && request.hasHadResponseDelivered()) { //告诉服务端没有有效的响应数据 request.notifyListenerResponseNotUsable(); //继续循环,获取队列中的下一个请求 continue; } //在工作线程将数据转换成Response对象 Response<?> response = request.parseNetworkResponse(networkResponse); //开始缓存 if (request.shouldCache() && response.cacheEntry != null) { mCache.put(request.getCacheKey(), response.cacheEntry); } //标记当前响应已经交给客户端 request.markDelivered(); //发送响应数据给客户端 //主要是回调Listener接口,通知客户端获取数据 mDelivery.postResponse(request, response); request.notifyListenerResponseReceived(response); } catch (VolleyError volleyError) { } catch (Exception e) { } } }
上面的代码执行流程也清晰,简单来说就是不断从请求队列中获取一个请求,拿到一个Request对象之后其核心逻辑也就是调用BasicNetwork对象的performRequest获取NetworkResponse对象;然后调用Request的parseNetworkResponse方法来构架自己所需要的响应对象。
RequestQueue简单描述:
注意上面说到了请求队列的东西,在volley中用RequestQueue来表示volley的请求队列,该类有如下属性:
//记录当前请求对象 private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>(); /** 缓存相关(本篇博文暂且不谈) */ private final PriorityBlockingQueue<Request<?>> mCacheQueue = new PriorityBlockingQueue<>(); /** 网络请求队列(支持线程优先级的) */ private final PriorityBlockingQueue<Request<?>> mNetworkQueue = new PriorityBlockingQueue<>();
可以看出RequestQueue一个优先级阻塞队列mNetworkQueue来添加请求。本文暂且不谈缓存功能。先来分析分析volley怎么向该队列添加请求对象,在RequestQueue中有add方法:
public <T> Request<T> add(Request<T> request) { //设置request所属的队列 request.setRequestQueue(this); //此处省略部分代码 if (!request.shouldCache()) { mNetworkQueue.add(request); return request; } //此处省略部分代码 return request; }
抛开缓存等功能(省略的代码)不说,add方法也就是向队列中不断添加Request对象,然后各个请求对象与请求队列进行绑定,简单的关系如图所示:
然后这些队列中的请求对象又被NetworkDispatcher不断获取发起网络请求。在RequestQueue中提供了start方法来开启NetworkDispatcher线程:
public void start() { // 默认 mDispatchers.length=4,开启四个 for (int i = 0; i < mDispatchers.length; i++) { NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery); mDispatchers[i] = networkDispatcher; networkDispatcher.start(); } }
在volley中一共开启了四个NetworkDispatcher线程对象来从同一个队列中获取请求对象,然后不断发起http请求,结合以上说明,volley的请求过程可以入下图表示:
那么客户端是怎么拿到这些数据的呢?就且听下回分解吧。
- Volley源码解析(二)
- Volley源码解析(二)
- Volley 源码解析(二)
- Volley源码解析(二)
- 【Volley】Volley源码解析
- Volley源码解析(二):RequestQueue
- volley源码解析(二)--Request<T>类的介绍
- Android Volley源码分析(二) 核心功能解析
- Volley源码解析<二> 整体框架和入口
- Volley框架使用与源码解析(二)
- 流行网络库第(二)篇---Volley源码解析
- Volley源码解析(二)——CacheDispatcher
- volley源码解析
- Volley 源码解析
- Volley 源码解析
- Volley 源码解析
- Volley 源码解析
- Volley 源码解析
- 纯CSS箭头
- Dialog自定义上下文花式菜单
- Python中time模块详解
- ubuntu16.04 挂载硬盘到/mnt
- 支付宝SDK接入详细指南(附官方支付demo)
- Volley源码解析(二)
- [特斯拉组件]ios高性能PageController
- ajax 轮询请求后台服务器
- HTML添加输入框,按钮。
- 查询SQLSERVER表结构脚本
- struct timeval结构体 以及 gettimeofday()函数
- 面试笔试整理7:SQL问题整理
- 设计模式-单一职责原则
- 第二章 HTTP报文