CacheDispatcher也是volley的核心类之一。
跟NetworkDispatcher一样,CacheDispatcher也是一个线程,该线程的作用就是从缓存队列中获取request,根据request的cacheKey从缓存Cache内获取该request的响应。在RequestQueue内,会对所有的request进行分发,如果一个request是可以被缓存的,那么就会分发到缓存队列中。需要注意的是,在volley中只会创建一个缓存调度线程,而会创建默认的四个网络调度线程。
重要的成员变量:
/** The queue of requests coming in for triage. 缓存请求队列,缓存调度线程会一直从该队列中取请求*/
private final BlockingQueue<Request> mCacheQueue;
/** The queue of requests going out to the network. 网络请求队列*/
private final BlockingQueue<Request> mNetworkQueue;
/** The cache to read from. 缓存*/
private final Cache mCache;
/** For posting responses. 响应传递机制*/
private final ResponseDelivery mDelivery;
工作流程:
1.在构造方法内会传入这四个成员变量,缓存调度线程是在RequestQueue的start()方法内创建并启动的,一start就开始执行线程的run方法。
public CacheDispatcher(BlockingQueue<Request> cacheQueue,
BlockingQueue<Request> networkQueue, Cache cache,
ResponseDelivery delivery) {
mCacheQueue = cacheQueue;
mNetworkQueue = networkQueue;
mCache = cache;
mDelivery = delivery;
}
2.在run方法内,首先初始化缓存操作 mCache.initialize(); 主要是如果没有缓存目录就创建缓存目录,如果缓存目录已经存在就读取缓存。
3.由于缓存调度线程会一直存在,因此在run内部是用while(true)来括起来的,通网络调度线程是一样的。
4.先从缓存队列中读取request,如果缓存队列为空,那么阻塞在这里,一直等待。
// Get a request from the cache triage queue, blocking until
// at least one is available.从缓存请求队列中取出一个请求,这是一个阻塞的方法,当缓存请求队列中没有请求时会一直等待,直到取到一个请求
final Request request = mCacheQueue.take();
5.从缓存队列中获取到request后
// If the request has been canceled, don't bother dispatching
// it.先判断从缓存请求队列中拿到的请求是否已经被取消了
if (request.isCanceled()) {
request.finish("cache-discard-canceled");
continue;
}
// Attempt to retrieve this item from cache.检查缓存中是否已经存在该请求的数据体
Cache.Entry entry = mCache.get(request.getCacheKey());
//为空,表示缓存中没有该请求的响应数据体
if (entry == null) {
request.addMarker("cache-miss");
// Cache miss; send off to the network dispatcher.缓存中没有数据,因此需要将该请求放到网络请求队列中
mNetworkQueue.put(request);
continue;
}
// If it is completely expired, just send it to the network.如果该请求的数据体已经过期,那么闲将数据体赋值给请求,然后将该请求添加到网络请求队列中去获取最新的数据
if (entry.isExpired()) {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
mNetworkQueue.put(request);
continue;
}
6.接下来是从request内获取响应数据
// We have a cache hit; parse its data for delivery back to the
// request. 既然到这里了,那么表示缓存中存在请求的响应数据
request.addMarker("cache-hit");
//依据缓存的数据,创建一个响应。参数为缓存中响应的数据体和响应头信息
Response<?> response = request
.parseNetworkResponse(new NetworkResponse(entry.data,
entry.responseHeaders));
request.addMarker("cache-hit-parsed");
if (!entry.refreshNeeded()) {
// Completely unexpired cache hit. Just deliver the
// response. 如果该响应依然新鲜那么就 直接分发,不需要去网络重新请求
mDelivery.postResponse(request, response);
} else {
//这种情况表示,缓存中的响应数据存在,但是需要刷新
// Soft-expired cache hit. We can deliver the cached
// response,
// but we need to also send the request to the network for
// refreshing.
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) {
// Not much we can do about this.
}
}
});
}
缓存调度线程就是这些了。
demo下载:http://download.csdn.net/detail/vvzhouruifeng/8747599