在《Volley源码解析(一)》和《Volley源码解析(二)》中简单讲解了Volley的内部工作原理,一言以蔽之就是:创建请求Request对象,然后将请求对象放入队列RequestQueue中,开启线程NetworkDispatcher不断从线程中获取请求对象,然后执行请求并返回响应对象。具体的细节可参考上面两篇博文,在此不细说,关于Volley的使用可以参考其官方文档。

其实对于android来说,大部分网络请求的业务都是通过接口获取数据然后对UI进行渲染;对于Volley来说你可以在任意的线程(UI线程或者非UI线程)创建Request对象,但是通过NetworkDispatcher发起网络请求然后完成数据解析后,最终解析后的数据会传给UI线程(Main Thread)来使用。那么这个过程是怎么实现的呢?在NetWorkDispatcher这个thread的run方法的内部有如下一句代码(详见《Volley源码解析(二)》):

 //主要是回调Listener接口,通知客户端获取数据mDelivery.postResponse(request, response);

事实上这段代码就是将解析后的response对象交给客户端使用,确切的说是在将数据交给main thread使用,这个mDelivery是ResponseDelivery接口,其具体在Volley的具体体现是ExecutorDelivery。那么mDelivery是什么时候初始化的呢?

在初始化请求队列RequestQueue对象的时候会通过Volley.newRequestQueue(context) 几经辗转会调用:

 public RequestQueue(Cache cache, Network network, int threadPoolSize) {this(cache, network, threadPoolSize,new ExecutorDelivery(new Handler(Looper.getMainLooper())));}

可以看出mDelivery变量的具体实例就是ExecutorDelivery,且该对象包含一个Handler对象,到此为止Volley的工作总体思路就不难猜出了:
1、异步线程发起网络请求
2、将请求包换的数据通过handler发送给main thread
这样就Volley就保证了获取网络数据回调更新UI界面过程,关于handler的工作机制可以参考博主的《android消息处理机制详解》

下面就看看ExecutorDelivery的post方法都作了写什么?

 private final Executor mResponsePoster;public ExecutorDelivery(final Handler handler) {// Make an Executor that just wraps the handler.//该Executor只是将Runable经过hanler重新包装一下,mResponsePoster = new Executor() {@Overridepublic void execute(Runnable command) {handler.post(command);}};}

从上面代码来看ExecutorDelivery的作用就是将交给Executor对象的Runnable交给handler处理,所以现在就可以看看post方法都作了写什么:

 @Overridepublic void postResponse(Request<?> request, Response<?> response) {postResponse(request, response, null);}@Overridepublic void postResponse(Request<?> request, Response<?> response, Runnable runnable) {mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));}

上面代码很简单,就是将ResponseDeliveryRunnable交给mResponsePoster这个Executor,最终交给handler处理。所以我们来看看ResponseDeliveryRunnable都作了写什么:

 public void run() {//省略部分代码if (mResponse.isSuccess()) {mRequest.deliverResponse(mResponse.result);} else {mRequest.deliverError(mResponse.error);}//省略部分代码}

上面的逻辑也很简单,就是将回调相关接口来通知客户端网络返回结果,如果失败的话回调ErrorListener接口,将错误原因交给客户端,成功则交给Request对象的子类来处理(因为deliverResponse是一个抽象方法)。以StringRequest对象来举例,其deliverResponse方法实现如下:

  @Overrideprotected void deliverResponse(String response) {if (mListener != null) {mListener.onResponse(response);}}

所以如果如果以StringRequest请求对象对正确和错误的响应都感兴趣的话,可以如下构建StringRequest对象:

  RequestQueue queue = Volley.newRequestQueue(this);String url = "http://www.baidu.com";//请求成功的接口Response.Listener<String> requestSuccessListener = new Response.Listener<String>() {@Overridepublic void onResponse(String response) {Log.i("VolleryTest","请求成功"+response);}};//请求失败的接口Response.ErrorListener errorListener = new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError error) {Log.i("VolleryTest","请求失败");error.printStackTrace();}};//构建请求对象:此处为get请求      StringRequest request = new StringRequest( url,requestSuccessListener,errorListener);queue.add(request);

运行上述代码发现打印请求失败,也就是说走了ErrorListener,并且Volley丢给我一个内部的log:

Unexpected response code 302

奇哉怪也,使用okhttp请求百度首页并没有出现这个错误,于是追踪其源码,在BasicNetWork这个类中找到类原因(这个类具体干嘛的,参考博主的其他两篇volley博客,在此不细说):

  if (statusCode < 200 || statusCode > 299) {throw new IOException();}

一目了然,Volley对于http的状态码作了判断,不满足200 =

 VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());

所以从对状态码的处理来看,OKhttp的处理比Volley理智多了,并没有一棒子打死。

Volley对http方法的支持

我们知道http支持get,post,put,delete等方法,那么volley又是支持哪些http的方法呢?查看Request代码可以发现volley对常用的http方法都作了支持:

 /*** Supported request methods.*/public interface Method {int DEPRECATED_GET_OR_POST = -1;int GET = 0;int POST = 1;int PUT = 2;int DELETE = 3;int HEAD = 4;int OPTIONS = 5;int TRACE = 6;int PATCH = 7;}

get请求不用说,下面来简单分析下post请求是怎么实现的,确切的收是分析post请求是怎么携带参数的。在HurlStack类中提供了一个setConnectionParametersForRequest方法:

static void setConnectionParametersForRequest(HttpURLConnection connection,Request<?> request) {switch (request.getMethod()) {case Method.POST:connection.setRequestMethod("POST");addBodyIfExists(connection, request);break;}}

如果是post请求,则会调用addBodyIfExists方法来组建参数(如果有参数的话):

 static void addBodyIfExists(HttpURLConnection connection, Request<?> request) {byte[] body = request.getBody();//省略组建post参数的代码}

addBodyIfExists的第一步是通过Request对象的getBody方法来获取post请求所需的参数,所以进度该方法看看是怎么回事儿:

  public byte[] getBody(){//通过getParams方法获取post请求参数Map<String, String> params = getParams();if (params != null && params.size() > 0) {return encodeParameters(params, getParamsEncoding());}return null;}

简单明了,原来post,delete,等请求参数的构建是通过Request对象的getParams() 方法来实现的:

 protected Map<String, String> getParams() {return null;}

该方法是一个protected方法,所以如果以StringReqeust 对象发起post请求的话,那么代码就该是如下所示 了:

new StringRequest(Request.Method.POST,url,requestSuccessListener,errorListener) {@Overrideprotected Map<String, String> getParams()  {Map<String,String> postParms = new HashMap<>();postParms.put("xxx","xxxx");return postParms;}};

不过看到这儿我总感觉怪怪的,本来是设置参数,提供的却是 getParams方法,而不是set方法,从设计上来说多少有点不合理的感觉。OKhttp对http请求方法的封装从代码设计角度来说就优雅的多了,OKhttp有点严格将请求和请求体分成两个对象Request和RequestBody,有点模仿html form表单请求的味道,想要了解更多的话可以参考《Okhttp发起http请求概述》

到此为止volley系列源码分析就结束了,至于volley的缓存因为其实现原理也很简单,在博主的volley系列中就不做具体解说了

Volley源码解析(三)相关推荐

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

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

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

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

  3. Disruptor源码解析三 RingBuffer解析

    目录 系列索引 前言 主要内容 RingBuffer的要点 源码解析 系列索引 Disruptor源码解析一 Disruptor高性能之道 Disruptor源码解析二 Sequence相关类解析 D ...

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

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

  5. OkHttp3源码解析(三)——连接池复用

    OKHttp3源码解析系列 OkHttp3源码解析(一)之请求流程 OkHttp3源码解析(二)--拦截器链和缓存策略 本文基于OkHttp3的3.11.0版本 implementation 'com ...

  6. ReactiveSwift源码解析(三) Signal代码的基本实现

    上篇博客我们详细的聊了ReactiveSwift源码中的Bag容器,详情请参见<ReactiveSwift源码解析之Bag容器>.本篇博客我们就来聊一下信号量,也就是Signal的的几种状 ...

  7. 并发编程与源码解析 (三)

    并发编程 (三) 1 Fork/Join分解合并框架 1.1 什么是fork/join ​ Fork/Join框架是JDK1.7提供的一个用于并行执行任务的框架,开发者可以在不去了解如Thread.R ...

  8. Android之Volley 源码解析

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

  9. 前端入门之(vuex源码解析三)

    上两节前端入门之(vuex源码解析二)我们把vuex的源码大概的撸了一遍,还剩下(插件.getters跟module),我们继续哈~ 插件童鞋们可以去看看vuex在各个浏览器的状态显示插件,小伙伴可以 ...

  10. 拆轮子-RxDownload2源码解析(三)

    本文为博主原创文章,未经允许不得转载 造轮子者:Season_zlc 轮子用法请戳作者链接 ↑ 前言 本文主要讲述 RxDownload2 的多线程断点下载技术. 断点下载技术前提 服务器必须支持按 ...

最新文章

  1. 《学习vi编辑器》的学习笔记1
  2. HAOI2014 走出金字塔
  3. Xamarin XAML语言教程基本页面ContentPage占用面积
  4. oracle手动删除数据库
  5. 深度学习图像超分辨率最新综述:从模型到应用
  6. Oracle数据库order by排序查询分页比不分页还慢问题解决办法
  7. html文档是哪个版本,Pro010-从零开始HTML[#010]——5分钟-HTML 文档类型版本
  8. node-inspector调试工具使用方法
  9. python爱心代码_母亲节快到了,用Python给老妈写个祝福小程序吧~
  10. 一本关于网上支付解决方案的迷你百科全书
  11. 基本的广告法违禁词、违规词以及敏感词大全
  12. Oracle优化的几个简单步骤
  13. Redis高可用群集——主从复制+哨兵模式
  14. 这家山炮公司,居然让腾讯又有了梦想!?
  15. 【1】Kali破解家用WI-FI密码 - WEP加密
  16. python中并集符号_python中列表之间求差集、交集、并集
  17. matlab圆锥曲线,圆锥曲线:MATLAB绘制椭圆方程的图像 来充电吧
  18. 基于边缘计算网关的PLC设备远程监控系统
  19. windows10搜索框不能搜索解决方法
  20. 期末学生HTML个人网页作业作品~蓝色的异清轩响应式个人博客模板源码~bootstrap响应式博客网站模板html...

热门文章

  1. Javascript:使用js将数据导出到excel/csv
  2. kafka可视化界面kibana_kafka日志同步至elasticsearch和kibana展示
  3. NodeJS连接MySQL
  4. catkin_make和cmake
  5. MyBatis之sql映射文件
  6. a的n次方的快速算法及大数相乘
  7. x264编码详细文字全过程
  8. android 图片设置圆角
  9. 并发容器Map之一:ConcurrentHashMap原理(jdk1.8)
  10. 水晶报表-推拉模式实例