所有的请求都是先经过CacheDispatcher类处理,然后如果需要进行进行处理才进入到NetworkDispatcher。原因是因为在RequestQueue的add()方法中是这样的:
// 如果不能缓存,则将请求添加到网络请求队列中. 默认true
if (!request.shouldCache()) {
mNetworkQueue.add(request);
return request;
}
mCacheQueue.add(request);
因为Request的shouldCache方法默认返回为True。所以请求不会加入到mNetworkQueue;然后来看一看CacheDispatcher是怎么处理请求的:
@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 {
// 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. If false, we should continue issuing the request
if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
mNetworkQueue.put(request);
}
continue;
}
// If it is completely expired, just send it to the network.
//判断缓存响应是否过期
Log.e("test","====="+entry.isExpired());
if (entry.isExpired()) {
//过期
request.addMarker("cache-hit-expired");
//set cache
request.setCacheEntry(entry);
//If false, we should continue issuing the request
if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
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");
/** True if a refresh is needed from the original data source. */
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;
if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
// 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) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}
}
});
} else {
// request has been added to list of waiting requests
// to receive the network response from the first request once it returns.
mDelivery.postResponse(request, response);
}
}
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
}
}
}
经过各种情况的判断后如果需要重新请求就将请求加入mNetworkQueue,否则就通过mDelivery返回状态。其中maybeAddToWaitingRequests(request)方法如下:
/**
* Staging area for requests that already have a duplicate request in flight.
*
* <ul>
* <li>containsKey(cacheKey) indicates that there is a request in flight for the given cache
* key.</li>
* <li>get(cacheKey) returns waiting requests for the given cache key. The in flight request
* is <em>not</em> contained in that list. Is null if no requests are staged.</li>
* </ul>
*/
private final Map<String, List<Request<?>>> mWaitingRequests = new HashMap<>();
/**
* For cacheable requests, if a request for the same cache key is already in flight,
* add it to a queue to wait for that in-flight request to finish.
* @return whether the request was queued. If false, we should continue issuing the request
* over the network. If true, we should put the request on hold to be processed when
* the in-flight request finishes. //如果这是真的,我们应该搁置请求处理动态的请求完成。
*/
private synchronized boolean maybeAddToWaitingRequests(Request<?> request) {
String cacheKey = request.getCacheKey(); //url
// Insert request into stage if there's already a request with the same cache key
// in flight.
if (mWaitingRequests.containsKey(cacheKey)) {
// There is already a request in flight. Queue up. 排队等候
List<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);
if (stagedRequests == null) {
stagedRequests = new ArrayList<Request<?>>();
}
request.addMarker("waiting-for-response");
stagedRequests.add(request);
mWaitingRequests.put(cacheKey, stagedRequests);
if (VolleyLog.DEBUG) {
VolleyLog.d("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);
}
return true;
} else {
// Insert 'null' queue for this cacheKey, indicating there is now a request in
// flight.
mWaitingRequests.put(cacheKey, null);
//listener
request.setNetworkRequestCompleteListener(this);
if (VolleyLog.DEBUG) {
VolleyLog.d("new request, sending to network %s", cacheKey);
}
return false;
}
}
其实就是维护CacheDispatcher的内部类WaitingRequestManager的mWaitingRequests等待队列。
网友评论