前提
上一次講了Volley的核心RequestQueue
,如果沒(méi)有看過(guò)的話請(qǐng)參看Volley使用總結(jié)及源碼分析(一)楚昭,在其start方法中如庭,維護(hù)了五個(gè)線程,一個(gè)緩存線程和四個(gè)網(wǎng)絡(luò)線程舒岸,下面我們繼續(xù)分析绅作,在上一次提到注意線程初始化的時(shí)候傳入的參數(shù),那參數(shù)傳入之后到底做了什么操作蛾派?
緩存線程
public class CacheDispatcher extends Thread {
private static final boolean DEBUG = VolleyLog.DEBUG;
private final BlockingQueue<Request<?>> mCacheQueue;
private final BlockingQueue<Request<?>> mNetworkQueue;
private final Cache mCache;
private final ResponseDelivery mDelivery;
private volatile boolean mQuit = false;
public CacheDispatcher(
BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue,
Cache cache, ResponseDelivery delivery) {
//緩存請(qǐng)求隊(duì)列
mCacheQueue = cacheQueue;
//網(wǎng)絡(luò)請(qǐng)求隊(duì)列
mNetworkQueue = networkQueue;
//DiskBasedCache類(lèi)具體對(duì)象俄认,用于本地緩存
mCache = cache;
//將響應(yīng)傳遞回主線程
mDelivery = delivery;
}
//退出線程
public void quit() {
mQuit = true;
interrupt();
}
@Override
public void run() {
if (DEBUG) VolleyLog.v("start new dispatcher"); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//初始化緩存
mCache.initialize();
while (true) {
try {
final Request<?> request = mCacheQueue.take();
request.addMarker("cache-queue-take");
//判斷是否取消
if (request.isCanceled()) {
request.finish("cache-discard-canceled");
continue;
}
//當(dāng)前請(qǐng)求是否有緩存个少,
Cache.Entry entry = mCache.get(request.getCacheKey());
if (entry == null) {
request.addMarker("cache-miss");
//沒(méi)有緩存,加入到網(wǎng)絡(luò)請(qǐng)求隊(duì)列
mNetworkQueue.put(request);
continue;
}
//判斷緩存是否過(guò)期
if (entry.isExpired()) {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
//過(guò)期的話重新加入網(wǎng)絡(luò)請(qǐng)求隊(duì)列
mNetworkQueue.put(request);
continue;
}
//緩存沒(méi)有過(guò)期的話眯杏,解析緩存為請(qǐng)求的響應(yīng)
request.addMarker("cache-hit");
Response<?> response = request.parseNetworkResponse(
new NetworkResponse(entry.data, entry.responseHeaders));
request.addMarker("cache-hit-parsed");
//原始數(shù)據(jù)源是否需要刷新
if (!entry.refreshNeeded()) {
//將解析后的響應(yīng)使用Delivery分發(fā)
mDelivery.postResponse(request, response);
} else {
//重新請(qǐng)求網(wǎng)絡(luò)夜焦,刷新緩存
request.addMarker("cache-hit-refresh-needed");
request.setCacheEntry(entry);
response.intermediate = true;
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;
}
continue;
}
}
}
}
?代碼中加了中文注釋?zhuān)梢钥吹?code>CacheDispatcher繼承了Thread
,實(shí)現(xiàn)了run方法岂贩。構(gòu)造方法將傳入的四個(gè)參數(shù)保存在成員變量中茫经,quit方法設(shè)置取消標(biāo)志,中斷線程萎津。run方法中首先對(duì)mCache
進(jìn)行初始化卸伞,然后不斷從緩存請(qǐng)求隊(duì)列中取請(qǐng)求處理mCacheQueue.take();
,隊(duì)列為空則等待姜性,請(qǐng)求處理結(jié)束則將結(jié)果傳遞給ResponseDelivery 去執(zhí)行后續(xù)處理瞪慧。當(dāng)結(jié)果未緩存過(guò)、緩存失效或緩存需要刷新的情況下部念,該請(qǐng)求都需要重新進(jìn)入NetworkDispatcher去調(diào)度處理弃酌。
網(wǎng)絡(luò)線程
public class NetworkDispatcher extends Thread {
private final BlockingQueue<Request<?>> mQueue;
private final Network mNetwork;
private final Cache mCache;
private final ResponseDelivery mDelivery;
private volatile boolean mQuit = false;
public NetworkDispatcher(BlockingQueue<Request<?>> queue,
Network network, Cache cache,
ResponseDelivery delivery) {
//網(wǎng)絡(luò)請(qǐng)求隊(duì)列
mQueue = queue;
//具體執(zhí)行網(wǎng)絡(luò)交互
mNetwork = network;
//DiskBasedCache類(lèi)具體對(duì)象,用于本地緩存
mCache = cache;
//將響應(yīng)傳遞回主線程
mDelivery = delivery;
}
public void quit() {
mQuit = true;
interrupt();
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void addTrafficStatsTag(Request<?> request) {
// Tag the request (if API >= 14)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
}
}
@Override
public void run() {
//設(shè)置線程優(yōu)先級(jí)
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
while (true) {
//記錄開(kāi)始時(shí)間
long startTimeMs = SystemClock.elapsedRealtime();
Request<?> request;
try {
//從隊(duì)列中取出網(wǎng)絡(luò)請(qǐng)求
request = mQueue.take();
} catch (InterruptedException e) {
if (mQuit) {
return;
}
continue;
}
try {
request.addMarker("network-queue-take");
//判斷是否取消
if (request.isCanceled()) {
request.finish("network-discard-cancelled");
continue;
}
addTrafficStatsTag(request);
//performRequest中儡炼,調(diào)用HttpStack處理請(qǐng)求
NetworkResponse networkResponse = mNetwork.performRequest(request);
request.addMarker("network-http-complete");
if (networkResponse.notModified && request.hasHadResponseDelivered()) {
request.finish("not-modified");
continue;
}
//使用request的parseNetworkResponse方法解析妓湘,請(qǐng)求的網(wǎng)絡(luò)響應(yīng)
Response<?> response = request.parseNetworkResponse(networkResponse);
request.addMarker("network-parse-complete");
if (request.shouldCache() && response.cacheEntry != null) {
//添加緩存
mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
request.markDelivered();
//將解析后的響應(yīng)使用Delivery分發(fā)
mDelivery.postResponse(request, response);
} catch (VolleyError volleyError) {volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
parseAndDeliverNetworkError(request, volleyError);
} catch (Exception e) {
VolleyLog.e(e, "Unhandled exception %s", e.toString());
VolleyError volleyError = new VolleyError(e);
volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
mDelivery.postError(request, volleyError);
}
}
}
private void parseAndDeliverNetworkError(Request<?> request, VolleyError error) {
error = request.parseNetworkError(error);
mDelivery.postError(request, error);
}
}
?可以看到NetworkDispatcher
與CacheDispatcher
很像,主要是run方法中的流程不同乌询。設(shè)置線程優(yōu)先級(jí)榜贴,不斷從網(wǎng)絡(luò)請(qǐng)求隊(duì)列中取出網(wǎng)絡(luò)請(qǐng)求,調(diào)用BasicNetwork
中的performRequest
方法處理請(qǐng)求妹田,在該方法中調(diào)用HttpStack處理請(qǐng)求唬党,并將結(jié)果轉(zhuǎn)換為可被ResponseDelivery處理的NetworkResponse。使用request.parseNetworkResponse
處理網(wǎng)絡(luò)返回的響應(yīng)鬼佣,加入緩存驶拱,返回處理后的響應(yīng)結(jié)果。
總結(jié)
?默認(rèn)情況下晶衷,所有請(qǐng)求都會(huì)經(jīng)過(guò)緩存線程判斷蓝纲,如果存在緩存且沒(méi)有過(guò)期,則直接返回緩存的響應(yīng)晌纫,否則加入網(wǎng)絡(luò)線程中税迷,在網(wǎng)絡(luò)線程中,會(huì)調(diào)用HttpStack處理請(qǐng)求锹漱,返回的響應(yīng)使用request的parseNetworkResponse方法進(jìn)一步進(jìn)行解析箭养,并將結(jié)果緩存到本地。