前言
在 Android 开发编程的过程当中,无可避免地需要涉及到网络编程,这就需要我们开发者比较熟练地掌握网络编程。哈哈,今天就先从解析 Volley 开始吧!
1.0 Volley是什么
Volley 是在 2013 年的 Googel I/O 大会上面推出的一个 HTTP 库,它可以帮助 Android 应用更加方便地执行网络请求。它既可以访问网络取得数据,同时还可以访问网络取得图片。
2.0 Volley的优缺点
Volley 有以下的优点:
- 自动调度网络请求
- 高并发网络连接
- 通过标准的 HTTP cache coherence(高速缓存一致性)缓存磁盘的内存透明的响应
- 支持指定请求的优先级
- 撤销请求 API,或者指定取消请求队列中的一个区域
- 框架容易被定制。例如,定制重试或者回调功能
- 强大的指令(Strong ordering)可以使得异步加载网络数据并正确地显示到 UI 的操作更加简单
- 包含了调试与追踪工具
Volley 的缺点:
- 不适合用来下载大的数据文件
3.0 Volley的网络请求队列
使用 Volley 的流程是,创建一个 RequestQueue
(请求队列)对象,然后把 Request
(请求)提交给它。
1 | // 代码[1] |
上面代码逻辑主要是通过构造一个 StringRequest
的实例,然后把这个实例添加进请求队列 RequestQueue
里面。我们来查看注释 1 的 Volley.newRequestQueue(Context)
方法的源码:
1 | // 源码[2] |
从上面的源码可以看出,newRequestQueue(Context)
是 newRequestQueue(Context, HttpStack)
的重载方法,下面我们主要来看 newRequestQueue(Context, HttpStack)
方法,在注释 1 处通过 new File(File, String)
初始化构建一个 cacheDir
的缓存(这是一个名词),在注释 3 处,new DiskBasedCache(cacheDir)
为这个缓存分配了 5M 的存储空间;
回到注释 2, 当 SDK 的版本大于或等于 9 的时候,也就是 Android 的版本号大于或等于 2.3,则创建基于 HttpURLConnection
的 HurlStack
,否则就创建基于执行请求的 HttpClient
的 HttpClientStack
,然后在注释 3 处,通过 new RequestQueue(Cache, Network)
创建请求队列,我们来查看下 new RequestQueue(Cache, Network)
的源码:
1 | // 源码[3] |
构造方法 new RequestQueue(Cache, Network)
为网络请求分配了 4 条线程进行请求。对于 RequestQueue
这个类,主要的作用是作为一个线程池用于调度队列中的请求:当调用 add(Request)
将会把传进的请求(Request)在缓存队列(cache)或者网络队列(network)中解析,然后传递回主线程,也就是 代码[1] 里面的回调函数 onResponse(String)
和 onErrorResponse(VolleyError)
拿到回调的请求内容;
在 代码[1] 的注释 4 处,调用了 add(Request)
方法:
1 | // 源码[4] |
从上面的 add(Request)
方法的源码可以看出,主要的逻辑是:如果请求(request)不可以缓存,就直接添加进缓存队列,否则添加进缓存队列; 当拿到 mNetworkQueue
和 mCacheQueue
以后,就把请求返回并且调用 start()
方法(如 源码[2] 的注释 4),当查看 start()
方法的源码时候:
1 | // 源码[5] |
里面主要是创建 CacheDispatcher(BlockingQueue<Request<?>>, BlockingQueue<Request<?>>, Cache, ResponseDelivery)
的实例并通过 mCacheDispatcher.start()
开启缓存调度线程,和创建 NetworkDispatcher(BlockingQueue<Request<?>>,Network, Cache,ResponseDelivery)
的实例并通过 networkDispatcher.start()
开启网络调度线程。
4.0 网络调度线程NetworkDispatcher
网络调度线程 NetworkDispatcher
是一个继承于 Thread
的线程,通过查看其任务方法 run()
的源码:
1 | // 源码[6] |
网络调度的主要逻辑是,先判断网络请求有没有被取消,如果没有被取消,就通过 mNetwork.performRequest(request)
执行请求网络响应,拿到响应以后,先缓存在本地,然后再回调给主线程。
5.0 缓存调度线程CacheDispatcher
缓存调度线程 CacheDispatcher
的源码如下所示:
1 |
|
同样地,如果请求没有被取消,就开始在取回本地的缓存,当本地的缓存不存在、丢失或者已经过期,就把请求添加到网络请求队列,当命中本地缓存,就把缓存的响应回调给主线程;
6.0 Volley原理解析
为了发送一个请求,你只需要构造一个请求并通过 add()
方法添加到 RequestQueue
中。一旦添加了这个请求,它会通过队列,通过一系列的调度,然后得到原始的响应数据并返回。
当执行 add()
方法时,Volley触发执行一个缓存处理线程以及一系列网络处理线程。当添加一个请求到队列中,它将被缓存线程所捕获并触发: 如果这个请求可以被缓存处理,那么会在缓存线程中执行响应数据的解析并返回到主线程。如果请求不能被缓存所处理,它会被放到网络队列中。网络线程池中的第一个可用的网络线程会从队列中获取到这个请求并执行HTTP操作,解析工作线程的响应数据,把数据写到缓存中并把解析之后的数据返回到主线程。
一个请求的生命周期
小结
到此,Volley 库的分析就到先到此暂时结束了。这次,笔者主要是就当一个请求添加进请求队列之后,到其返回响应的过程进行了分析,了解到了 Volley 是如何把一个请求进行调度,然后得到响应并返回的。哈哈,感谢你的阅读…
源码下载 TestVolley