CacheDispatcher
缓存线程默认只有一个线程,负责从缓存队列取出请求并执行
下面是其执行的主要源码:
public void run() {
if (DEBUG) VolleyLog.v("start new dispatcher");
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// Make a blocking call to initialize the cache.
mCache.initialize(); //计算缓存目录所有文件大小
while (true) {
try {
// Get a request from the cache triage queue, blocking until
// at least one is available.
final Request<?> request = mCacheQueue.take();
request.addMarker("cache-queue-take");
// 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;
}
// 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.
}
}
});
}
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
}
}
}
按照上面顺序执行过程,可总结为:
- mCacheQueue.take()从阻塞缓存队列取出一个请求
- 如果请求已经取消就finish结束这个请求
- 根据请求的url查看文件换成中是否已经有这个缓存,没有缓存或者缓存已经过期都需要重新请求,所以将其加入网络请求队列
- 有缓存,则取出缓存数据构建一个Response对象,这里再次判断这个缓存有没有立即刷新的标识,有或者没有这个标识都需要将response回调给它的请求者,只是有这个标识还要在请求一次数据,即把Request请求加入网络对象中去
关于缓存如何去使用?
通常我们使用Volley并没有过多的去设置我们的请求使用缓存,如果需要使用,在请求Request的时候要先去设置缓存标识:
public final Request<?> setShouldCache(boolean shouldCache) {
mShouldCache = shouldCache;
return this;
}
最后这个缓存还需要由我们自己去存储,Volley所有的请求完成后都会回调这个parseNetworkResponse,如果我们自定义请求,,我们重写这个方法,在这个方法中存储好我们的数据即可,可以参考下面StringRequest的方法去保存:
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
小知识点
后台线程尽量为其设置一个优先级,以便线程调度器更好的调度线程
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
子线程退出方法
public void quit() {
mQuit = true;
interrupt();
}
@Override
public void run() {
if (DEBUG) VolleyLog.v("start new dispatcher");
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// Make a blocking call to initialize the cache.
mCache.initialize(); //计算缓存目录所有文件大小
while (true) {
try {
.....
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
}
}
}
最后,由于CacheDispatcher执行比较简单,再次就不画流程图了
网友评论