Volley源码解析
使用Volley整体流程:
总体设计图
1. Request类型及类图
2. RequestQueue
/frameworks/volley/src/com/android/volley/RequestQueue.java
PriorityBlockingQueue<Request<?>> mCacheQueue
PriorityBlockingQueue<Request<?>> mNetworkQueue
mCacheQueue 和 mNetworkQueue 都是用来存放Request的
当RequestQueue中add一个Request后,如果该请求不加入Cache则直接加入mNetworkQueue,等待Network处理该请求;或者先放入mCacheQueue等待CacheDispatcher的处理;
RequestQueue的start() 方法
RequestQueue的 add 方法
对于新add的request, 设置归属队列,放入mCurrentRequest 表示正在处理,并设置一下加入队列的顺序,
需要需要对该request进行Cache,
不需要Cache则直接放入networkQueue等待网络访问
需要放入cache,则要先查询是否已经有相同的请求在等待
如果没有,则直接放入CacheQueue等待调度,
如果有等待, 则也要加入mWritingRequests,排队等候
RequestQueue的 finish 方法
这个方法在Request#finish(String)中被调用, 用来表示Request已经完成,将在mCurrentRequests中移除;
如果要放入Cache, 则要在mWaitingRequests中相同的正在等待的请求移除, 然后将请求放到mCacheQueue中
RequestQueue的 cancelAll 方法
public void cancelAll(RequestFilter filter) —— 自己定义一个RequestFilter, 所有符合这个fiflter的都将被标志为 mCanceled = true;
public void cancelAll(final Object tag) —— 所有request.getTag() == tag 的 Request 都会被标志为 mCanceled = true;
/frameworks/volley/src/com/android/volley/toolbox/RequestFuture.java
3. Dispatch Thread
/frameworks/volley/src/com/android/volley/CacheDispatcher.java
public class CacheDispatcher extends Thread
Provides a thread for performing cache triage on a queue of requests. Requests added to the specified cache queue are resolved from cache. Any deliverable response is posted back to the caller via a {@link ResponseDelivery}. Cache misses and responses that require refresh are enqueued on the specified network queue for processing by a {@link NetworkDispatcher}.
- 它是一个Thread, 作用是 对 RequestQueue执行缓存调度;
- 从Cache中解析出来的Request 被添加到指定的CacheQueue.
- 任何可交付的response都被ResponseDelivery传回给调用者.
- 未命中的Cache & 需要刷新的reponse 都要被 NetworkDispatcher 添加到指定的 NetworkQueue
run函数流程图
/frameworks/volley/src/com/android/volley/NetworkDispatcher.java
public class NetworkDispatcher extends Thread
特殊点: TrafficStats.setThreadStatsTag(request.getTrafficStatsTag()); 流量统计API, 用来标记线程内部发生的数据传输情况
线程run()方法流程图
4. Get Data Interface部分
4.1 Cache 类型
/frameworks/volley/src/com/android/volley/Cache.java
/frameworks/volley/src/com/android/volley/toolbox/DiskBasedCache.java
/frameworks/volley/src/com/android/volley/toolbox/NoCache.java
4.2 网络访问组件:
/frameworks/volley/src/com/android/volley/toolbox/HttpStack.java
/frameworks/volley/src/com/android/volley/toolbox/HttpClientStack.java
/frameworks/volley/src/com/android/volley/toolbox/HurlStack.java
/frameworks/volley/src/com/android/volley/Network.java
/frameworks/volley/src/com/android/volley/toolbox/BasicNetwork.java
实现超类Network的performRequest方法
BasicNetwork.performRequest方法
将参数request提取关键数据,调用 mHttpStack.performRequest(request, headers) 发起网络访问, 分解反馈httpResponse的 statusCode 封装不同的 NetworkResponse;
如果中间发生了异常 例如 SocketTimeoutException, ConnectTimeoutException, 或者statusCode == HttpStatus.SC_UNAUTHORIZED || statusCode == HttpStatus.SC_FORBIDDEN, 那么根据 重试策略进行 重新访问
Delivery相关
/frameworks/volley/src/com/android/volley/ResponseDelivery.java
/frameworks/volley/src/com/android/volley/ExecutorDelivery.java
ExecutorDelivery的postResponse方法执行一个ResponseDeliveryRunnable线程,将response传给用户。
ResponseDeliveryRunnable线程run()函数流程如下:
Retry重试策略
/frameworks/volley/src/com/android/volley/RetryPolicy.java
/frameworks/volley/src/com/android/volley/DefaultRetryPolicy.java
Response类型
/frameworks/volley/src/com/android/volley/Response.java
/frameworks/volley/src/com/android/volley/NetworkResponse.java
几种错误处理
/frameworks/volley/src/com/android/volley/VolleyError.java
/frameworks/volley/src/com/android/volley/TimeoutError.java
/frameworks/volley/src/com/android/volley/NetworkError.java
/frameworks/volley/src/com/android/volley/NoConnectionError.java
/frameworks/volley/src/com/android/volley/ServerError.java
/frameworks/volley/src/com/android/volley/AuthFailureError.java
/frameworks/volley/src/com/android/volley/ParseError.java
登录相关
/frameworks/volley/src/com/android/volley/toolbox/Authenticator.java
/frameworks/volley/src/com/android/volley/toolbox/AndroidAuthenticator.java
2.2. Volley 中的概念
简单介绍一些概念,在详细设计中会仔细介绍。
Volley 的调用比较简单,通过 newRequestQueue(…) 函数新建并启动一个请求队列RequestQueue后,只需要往这个RequestQueue不断 add Request 即可。
Volley:Volley 对外暴露的 API,通过 newRequestQueue(…) 函数新建并启动一个请求队列RequestQueue。
Request:表示一个请求的抽象类。StringRequest、JsonRequest、ImageRequest 都是它的子类,表示某种类型的请求。
RequestQueue:表示请求队列,里面包含一个CacheDispatcher(用于处理走缓存请求的调度线程)、NetworkDispatcher数组(用于处理走网络请求的调度线程),一个ResponseDelivery(返回结果分发接口),通过 start() 函数启动时会启动CacheDispatcher和NetworkDispatchers。
CacheDispatcher:一个线程,用于调度处理走缓存的请求。启动后会不断从缓存请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery去执行后续处理。当结果未缓存过、缓存失效或缓存需要刷新的情况下,该请求都需要重新进入NetworkDispatcher去调度处理。
NetworkDispatcher:一个线程,用于调度处理走网络的请求。启动后会不断从网络请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery去执行后续处理,并判断结果是否要进行缓存。
ResponseDelivery:返回结果分发接口,目前只有基于ExecutorDelivery的在入参 handler 对应线程内进行分发。
HttpStack:处理 Http 请求,返回请求结果。目前 Volley 中有基于 HttpURLConnection 的HurlStack和 基于 Apache HttpClient 的HttpClientStack。
Network:调用HttpStack处理请求,并将结果转换为可被ResponseDelivery处理的NetworkResponse。
Cache:缓存请求结果,Volley 默认使用的是基于 sdcard 的DiskBasedCache。NetworkDispatcher得到请求结果后判断是否需要存储在 Cache,CacheDispatcher会从 Cache 中取缓存结果。
- 流程图
Volley 请求流程图
上图是 Volley 请求时的流程图,在 Volley 的发布演讲中给出,我在这里将其用中文重新画出。 - 详细设计
4.1 类关系图
这是 Volley 框架的主要类关系图
图中红色圈内的部分,组成了 Volley 框架的核心,围绕 RequestQueue 类,将各个功能点以组合的方式结合在了一起。各个功能点也都是以接口或者抽象类的形式提供。
红色圈外面的部分,在 Volley 源码中放在了toolbox包中,作为 Volley 为各个功能点提供的默认的具体实现。
通过类图我们看出, Volley 有着非常好的拓展性。通过各个功能点的接口,我们可以给出自定义的,更符合我们需求的具体实现。
多用组合,少用继承;针对接口编程,不针对具体实现编程。