一、Volley工作流程图:
继续从CacheDispatcher和NetworkDispatcher开始看起。
二、CacheDispatcher:
一个线程,用于调度处理走缓存的请求。启动后会不断从缓存请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery
去执行后续处理。当结果未缓存过、缓存失效或缓存需要刷新的情况下,该请求都需要重新进入NetworkDispatcher
去调度处理。
(一)看源码前,先看一下从其成员变量与处理流程:
(1). 成员变量
BlockingQueue<Request<?>> mCacheQueue
缓存请求队列
BlockingQueue<Request<?>> mNetworkQueue
网络请求队列
Cache mCache
缓存类,代表了一个可以获取请求结果,存储请求结果的缓存
ResponseDelivery mDelivery
请求结果传递类
(2). 处理流程图
(3)源码:
1、构造函数:一系列赋值初始化操作
/**
* Creates a new cache triage dispatcher thread. You must call {@link #start()}
* in order to begin processing.
*/
public CacheDispatcher(BlockingQueue<Request> cacheQueue, BlockingQueue<Request> networkQueue,
Cache cache, ResponseDelivery delivery) {
mCacheQueue = cacheQueue;
mNetworkQueue = networkQueue;
mCache = cache;
mDelivery = delivery;
}
提到使用CacheDispatcher时一定要调用start()方法;而
CacheDispatcher的创建与线程start都是在RequestQueue中的add()函数中实现的:
// Create the cache dispatcher and start it.
mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
mCacheDispatcher.start();
2、既然是线程,重点看其run()函数:
@Override
public void run() {
//设置优先级
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// Make a blocking call to initialize the cache.
//这里的Cache其实是DiskBasedCache,见附I
mCache.initialize();
/*****循环处理逻辑******/
while (true) {
try {
// 从缓存队列 mCacheQueue中取出一个Request;如果mCacheQueue为空,则阻塞进行忙等待
final Request request = mCacheQueue.take();
request.addMarker("cache-queue-take");
// 如果取出的Request请求已经被取消,则直接finish,处理下一个request
if (request.isCanceled()) {
request.finish("cache-discard-canceled");
continue;
}
// 尝试从缓存中获取request对应的结果
Cache.Entry entry = mCache.get(request.getCacheKey());
//为null,表示该cacheKey对应缓存结果不存在,则直接将request添加到mNetworkQueue中
if (entry == null) {
request.addMarker("cache-miss");
mNetworkQueue.put(request);
continue;
}
//如果缓存结果存在,但是已过期,同样也是将request添加到mNetworkQueue中
if (entry.isExpired()) {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
mNetworkQueue.put(request);
continue;
}
// 如果命中(hit)找到了对应的缓存结果,则解析其数据为Response并返回给该request
request.addMarker("cache-hit");
Response<?> response = request.parseNetworkResponse(
new NetworkResponse(entry.data, entry.responseHeaders));
request.addMarker("cache-hit-parsed");
// 还需判断缓存结果是否时间过久已经不新鲜,是否需要refresh
if (!entry.refreshNeeded()) {
// 不需要Refresh,则直接由mDelivery提交给相应的request
mDelivery.postResponse(request, response);
} else {
// 如果已经不新鲜,mDelivery依旧提交结果给request,
// 但同时要将Request传递给mNetworkQueue进行新鲜度验证
request.addMarker("cache-hit-refresh-needed");
request.setCacheEntry(entry);
// Mark the response as intermediate.
response.intermediate = true;
// Post the intermediate response back to the user and have
// the delivery then forward the request along to the network.
mDelivery.postResponse(request, response, new Runnable() {
@Override
public void run() {
try {
mNetworkQueue.put(request);
} catch (InterruptedException e) {
}
}
});
}
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
continue;
}
}
}
附I)这里的Cache实际是DiskBasedCache,mCache.initialize()实际上调用的是
DiskBasedCache.initialize():
/**
* Initializes the DiskBasedCache by scanning for all files currently in the
* specified root directory. Creates the root directory if necessary.
*/
public synchronized void initialize()
三、NetworkDispatcher
一个线程,用于调度处理网络的请求。启动后会不断从网络请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给 ResponseDelivery 去执行后续处理,并判断结果是否要进行缓存。
(1). 成员变量
BlockingQueue<Request<?>> mQueue
网络请求队列
Network mNetwork
网络类,代表了一个可以执行请求的网络
Cache mCache
缓存类,代表了一个可以获取请求结果,存储请求结果的缓存
ResponseDelivery mDelivery
请求结果传递类,可以传递请求的结果或者错误到调用者
(2). 处理流程图
(3).先看其构造函数,与CacheDispatcher的逻辑处理大致相同:
/**
* Creates a new network dispatcher thread. You must call {@link #start()}
* in order to begin processing.
*/
public NetworkDispatcher(BlockingQueue<Request> queue,
Network network, Cache cache,
ResponseDelivery delivery) {
mQueue = queue;
mNetwork = network;
mCache = cache;
mDelivery = delivery;
}
(4).其run()函数:
@Override
public void run() {
//设为后台进程
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Request request;
/*********循环处理逻辑********/
while (true) {
try {
// 从网络请求队列中取出request,同理mQueue为空时,也是忙等待
request = mQueue.take();
} catch (InterruptedException e) {
if (mQuit) {
return;
}
continue;
}
try {
request.addMarker("network-queue-take");
// 如果取出的Request请求已经被取消,则直接finish,处理下一个request
if (request.isCanceled()) {
request.finish("network-discard-cancelled");
continue;
}
// Tag the request (if API >= 14)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
}
// 通过Network执行Request,获得NetworkResponse,故网络请求的处理逻辑应该都封装在了Network中
NetworkResponse networkResponse = mNetwork.performRequest(request);
request.addMarker("network-http-complete");
// 用来验证新鲜度,(notModified=304)响应为304且请求已经有了Response传输情况
if (networkResponse.notModified && request.hasHadResponseDelivered()) {
request.finish("not-modified");
continue;
}
// 将NetworkResponse解析为Response
Response<?> response = request.parseNetworkResponse(networkResponse);
request.addMarker("network-parse-complete");
// 如果request可以被缓存,并且其请求实体补位空,则添加到mCache中
// TODO: Only update cache metadata instead of entire record for 304s.
if (request.shouldCache() && response.cacheEntry != null) {
mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
// 传输Response
request.markDelivered();
mDelivery.postResponse(request, response);
} catch (VolleyError volleyError) {
parseAndDeliverNetworkError(request, volleyError);
} catch (Exception e) {
VolleyLog.e(e, "Unhandled exception %s", e.toString());
mDelivery.postError(request, new VolleyError(e));
}
}
}