在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());//发起请求,返回NetWorkResponseNetworkResponse 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源码解析(二)相关推荐

  1. Volley 源码解析之图片请求

    一.前言 上篇文章我们分析了网络请求,这篇文章分析对图片的处理操作,如果没看上一篇,可以先看上一篇文章Volley 源码解析之网络请求.Volley 不仅仅对请求网络数据作了良好的封装,还封装了对图片 ...

  2. Volley 源码解析之网络请求

    Volley源码分析三部曲 Volley 源码解析之网络请求 Volley 源码解析之图片请求 Volley 源码解析之缓存机制 Volley 是 Google 推出的一款网络通信框架,非常适合数据量 ...

  3. http://a.codekk.com/detail/Android/grumoon/Volley 源码解析

    http://a.codekk.com/detail/Android/grumoon/Volley 源码解析

  4. 【深度学习模型】智云视图中文车牌识别源码解析(二)

    [深度学习模型]智云视图中文车牌识别源码解析(二) 感受 HyperLPR可以识别多种中文车牌包括白牌,新能源车牌,使馆车牌,教练车牌,武警车牌等. 代码不可谓不混乱(别忘了这是职业公司的准产品级代码 ...

  5. Android之Volley 源码解析

    原文来自:http://www.codekk.com  1. 功能介绍  1.1. Volley Volley 是 Google 推出的 Android 异步网络请求框架和图片加载框架.在 Googl ...

  6. erlang下lists模块sort(排序)方法源码解析(二)

    上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...

  7. Kubernetes学习笔记之Calico CNI Plugin源码解析(二)

    女主宣言 今天小编继续为大家分享Kubernetes Calico CNI Plugin学习笔记,希望能对大家有所帮助. PS:丰富的一线技术.多元化的表现形式,尽在"360云计算" ...

  8. Mobx 源码解析 二(autorun)

    前言 我们在Mobx 源码解析 一(observable)已经知道了observable 做的事情了, 但是我们的还是没有讲解明白在我们的Demo中,我们在Button 的Click 事件中只是对ba ...

  9. android网络框架retrofit源码解析二

    注:源码解析文章参考了该博客:http://www.2cto.com/kf/201405/305248.html 前一篇文章讲解了retrofit的annotation,既然定义了,那么就应该有解析的 ...

  10. Thrift源码解析(二)序列化协议

    概述 对于一个RPC框架,定义好网络数据的序列化协议是最基本的工作,thrift的序列化协议主要包含如下几种: TBinaryProtocol TCompactProtocol TJSONProtoc ...

最新文章

  1. AI现在能教你画画了
  2. POJ-3621 Sightseeing Cows 最优比率环、01分数规划
  3. java 序列化 例子_Java序列化和反序列化例子
  4. 微服务API模拟框架frock介绍
  5. PyTorch框架学习十五——可视化工具TensorBoard
  6. c语言综合编程,C语言编程入门——综合练习(一)
  7. 怎么把代码放图片里面进行注入_揭秘代码分层后的新世界
  8. 普强“千语”语音识别引擎应用场景
  9. 在python中编写socket服务端模块(二):使用poll或epoll
  10. SQL Server Management Studio格式化SQL工具(可免费)
  11. 【FFmpeg命令】jpg与yuv(批量)互转
  12. 人工智能的利弊?好处和危害都有哪些
  13. 手机也能拍照扫描?这些拍照扫描app方便又好用
  14. c语言单片机的电子琴课程设计,基于单片机的电子琴的设计
  15. 【EXCEL】去除多余行列
  16. mysql reads sql data_在其声明中使用DETERMINISTIC,NO SQL或READS SQL DATA并启用二进制日志记录...
  17. 嵌入式常用算法:时间触发下的嵌入式软件设计模式
  18. 如何配置一台深度学习主机?
  19. Tableau——蝴蝶图实现数据对比
  20. cocos2dx3.17.0安装到完整打包android流程

热门文章

  1. Axis2生成wsdl的一种方法
  2. c++中#pragma用法详解
  3. Redis和Memcache和MongoDB简介及区别分析(整理)
  4. Codeforces 486D Valid Sets (树型DP)
  5. 深入Java集合学习系列:SynchronousQueue实现原理
  6. Windows7 64位系统搭建Cocos2d-x 2.2.1最新版以及Android交叉编译环境(具体教程)
  7. SAM4E单片机之旅——22、GMAC和PHY的介绍与初始化
  8. 从0到1亿美元 ---- PopCap创始人John Vechey自述(zt)
  9. 如何在C++中调用C程序?(讲的比较清楚)
  10. 【C++编程技巧】函数多个返回值