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執行比較簡單,再次就不畫流程圖了