抽时间看了下Volley的源码,感觉这个框架还是很不错的,这里对其源码进行分析。
主要从以下几个方面分析:
- 简要介绍 Volley 的使用
- Volley 访问网络的整体流程
- 对源码中一些重要的类的总结
- 一些总结
简要介绍 Volley 的使用
这个不是文章的重点,所以就简单介绍一下。
|
|
更具体的使用可以参考博客 Volley使用
Volley 访问网络的整体流程
这里从使用方法开始进行分析。
首先通过 Volley#newRequestQueue() 创建请求队列。
在Volley类中,一共就提供了两个静态的重载方法 newRequestQueue()
主要看下 newRequestQueue(Context, HttpStack)
|
|
可以看到,其中主要创建了Network,HttpStack,RequestQueue,并启动了RequestQueue
最终网络访问就封装在HttpStack中,这个后面再看
先跟进到 RequestQueue#start()中看下
|
|
其中可以看到,就是启动了缓存派发器和网络派发器
在构建了请求队列后,发起请求只要把请求添加到请求队列中就好了,接下来看下RequestQueue#add()代码
这里挑一些主要的代码看
|
|
从上面代码中可以看到,请求需要缓存的话,会加入到缓存队列中,交给缓存派发器处理,否则交给网络请求派发器处理
接下来看下缓存派发器对请求的处理
由于 CacheDispatcher 和 NetworkDispatcher 都是继承自 Thread , 所以主要看其 run() 函数
|
|
从上面可以看到,代码不多,也很好理解,如果有缓存,就取出来去处理,没有或者过期,就加入到网络请求队列中去请求,需要网络请求的有几个地方:1. 请求不需要缓存 2. 请求在缓存中没有找到 3. 请求的缓存过期 4. 请求的缓存需要刷新
接下来就看下网络请求派发器
NetworkDispatcher 也是继承 Thread,所以也直接看 run() 函数
|
|
可以看到,在 NetworkDispatcher 中,最主要的就是调用了 mNetwork.performRequest(request) 执行网络请求,而在 Network 是个接口,具体实现类是 BasicNetwork,在BasicNetwork#performRequest()中调用 httpResponse = mHttpStack.performRequest(request, headers),这里的 mHttpStack 就是前面看到的 HurlStack 和 HttpClientStack。而在 HttpStack 的 performRequest() 中就是具体的网络请求,看下 HurlStack 的。
|
|
在上面我们看到,最终会调用 ResponseDelivery#postResponse()
ExecutorDelivery 是 ResponseDelivery 的实现类,可以看下 ExecutorDelivery#postResponse()
|
|
|
|
以上就是请求的主要流程了,下面附上一张流程图
上面分析中没有提到 Volley 中的重试机制,其实在 BasicNetwork#performRequest() 中实现了失败重试机制。
|
|
对源码中一些重要的类的总结
其实在上面讲流程的时候已经分析了主要的类了,这里主要做个总结。
Volley中主要的类有这些:
- Volley: 提供了构建 RequestQueue 的统一方法,我们也可以不通过这个而是自己构建 RequestQueue
- RequestQueue: 负责分发请求到不同的请求队列中
- CacheDispatcher: 处理缓存请求
- NetworkDispatcher: 处理网络请求
- ResponseDelivery: 获取请求后进行处理
- Cache: 缓存接口,具体实现类有 DiskBaseCache
- Network: 网络接口,具体实现类有 BasicNetwork
- HttpStack: 真正执行请求,具体实现类有 HurlStack HttpClientStack
- Request: 封装请求信息并处理回复,具体实现类有 StringRequest JsonRequest
- Response: 封装返回的信息,具体实现类有 NetworkResponse
一些总结
最后再分析一下为什么在 Volley 的 listener 的中可以直接更新UI。
在前面 Volley#newRequestQueue() 中有调用到如下代码
|
|
跟进会发现最后调用的是
|
|
我们上面也提到,最后的 Response 是通过 ResponseDelivery#postResponse() 来分发,而 ExecutorDelivery 是 ResponseDelivery 的实现类,而这个构造函数的实现如下:
|
|
请求最终都会调用 handler.post(),而这个 handler 是上面通过 new Handler(Lopper.getMainLopper()) 得到的,所以请求的处理就通过这里分发到主线程中了,也就自然可以更新 UI 了。
最后:
通过对 Volley 源码的分析,可以发现, Volley 框架的拆装性很强,框架默认使用的是 HttpUrlConnection 和 HttpClient 来实现网络请求,如果我们想换成其他,比如okhttp,只要继承 HttpStack 并重写 performRequest() 来处理请求就可以了。对于请求,框架默认提供了 StringRequest 和 JsonRequest,一般情况下这两个是足够用了,但是特别情况下,我们只要继承 Request 并重写 deliverResponse() 和 parseNetworkResponse() 就可以了。
以前自己也有实现过网络框架,相比之下,还是有很多不足,通过阅读源码,还是学到了很多。