上節寫到關於
Vollery
的前半部分,需要查看的點擊 這裏 , 這次主要查看當我們真正add request
的時候做進一步查看。
我們還是從使用的方法作爲我們的切入點:
mQueue.add(postRequest);//當我們向隊列中添加一個網絡請求
跟進,查看 RequestQueue#add()
方法:
/**
* Staging area for requests that already have a duplicate request in
* flight.
* 存儲有重複請求的request暫存區,我個人認爲就是如果 正在處理A發出的一個請求,此時又來一個A發出同樣的一個請求,那麼第二個請求就會暫時保存在這個集合中
*/
private final Map<String, Queue<Request<?>>> mWaitingRequests = new HashMap<String, Queue<Request<?>>>();
public <T> Request<T> add(Request<T> request) {
// Tag the request as belonging to this queue and add it to the set of
// current requests.
request.setRequestQueue(this);
synchronized (mCurrentRequests) {
mCurrentRequests.add(request);
}
// Process requests in the order they are added.
//按照添加請求的順序處理請求
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue");
// If the request is uncacheable, skip the cache queue and go straight
// to the network.
//判斷是否可以緩存了,不緩存就添加到網絡請求隊列中去return,前面已經說過這個 mNetworkQueue 存儲管理網絡請求隊列的
//默認是可以緩存的,在Request的構造方法可以看到
//public Request(int method, String url, ErrorListener listener) {
// this.mShouldCache = true;
// }
if (!request.shouldCache()) {
mNetworkQueue.add(request);
return request;
}
//直接到下面
// Insert request into stage if there's already a request with the same
// cache key in flight.
synchronized (mWaitingRequests) {
//首先查看是否緩存過,取key
String cacheKey = request.getCacheKey();
//如果緩存過
if (mWaitingRequests.containsKey(cacheKey)) {
// There is already a request in flight. Queue up.
Queue<Request<?>> stagedRequests = mWaitingRequests
.get(cacheKey);
if (stagedRequests == null) {
stagedRequests = new LinkedList<Request<?>>();
}
stagedRequests.add(request);
//添加到暫時存儲隊列中
mWaitingRequests.put(cacheKey, stagedRequests);
} else {
//第一次請求,應該是進入到這裏的
// Insert 'null' queue for this cacheKey, indicating there is
// now a request in
// flight.
//添加一個 null 隊列,表示有一個請求正在進行
mWaitingRequests.put(cacheKey, null);
//添加到緩存隊列中,那麼我們接下來重點查看CacheDispatcher#run方法
mCacheQueue.add(request);
}
return request;
}
}
接下來就到 CacheDispatcher#run()
方法了,因爲裏面有值了。
public void run() {
Process.setThreadPriority(10);
//初始化緩存類型有兩種目前:NoCache() 和 DiskBaseCache()
this.mCache.initialize();
//嵌套了好多 while 循環
while(true) {
while(true) {
while(true) {
while(true) {
try {
//從緩存隊列中取出,在之前第一篇文章時,沒展示下半部分,這次有請求就可以看下里面的邏輯了。
final Request<?> request = (Request)this.mCacheQueue.take();
request.addMarker("cache-queue-take");
//請求未取消
if (request.isCanceled()) {
request.finish("cache-discard-canceled");
} else {
//拿到緩存結果,請求信息都保存一個叫Entry內部類中
Entry entry = this.mCache.get(request.getCacheKey());
//有可能取出的緩存爲null
if (entry == null) {
request.addMarker("cache-miss");
//如果清空了緩存,那就重新添加到網絡請求隊列中去
this.mNetworkQueue.put(request);
} else if (!entry.isExpired()) {//判斷是否過期
request.addMarker("cache-hit");
//拿到請求結果response
Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));
request.addMarker("cache-hit-parsed");
//表示是否需要重新刷新
if (!entry.refreshNeeded()) {
//不需要的話就直接分發給主線程了
this.mDelivery.postResponse(request, response);
} else {
//需要刷新,就重新進行網絡請求
request.addMarker("cache-hit-refresh-needed");
request.setCacheEntry(entry);
response.intermediate = true;
this.mDelivery.postResponse(request, response, new Runnable() {
public void run() {
try {
////需要刷新,就重新進行網絡請求
CacheDispatcher.this.mNetworkQueue.put(request);
} catch (InterruptedException var2) {
;
}
}
});
}
} else {
//表示過期了,也重新進行請求
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
this.mNetworkQueue.put(request);
}
}
} catch (InterruptedException var4) {
if (this.mQuit) {
return;
}
}
關於 CacheDispatcher#run
類我畫了一張圖示:
從這裏我們知道,網絡請求首先需要mCacheDispatcher
判斷是否已緩存,若緩存了則直接 postResponse
如果沒有,則重新進行網絡請求,我們就直接添加到 mNetworkQueue
中,那第一次請求,肯定還未緩存, 那我們下面就又可以看這個 NetworkDispatcher#run
方法了,因爲此時隊列中有請求了,接下來我們再返回查看:
NetworkDispatcher#run()
方法:
public void run() {
//設置線程優先級
Process.setThreadPriority(10);
while(true) {
Request request;
while(true) {
try {
//從這個網絡請求隊列中中取出一條request
//第二次這裏有了,因爲我們add 了 一個 request
request = (Request)this.mQueue.take();
break;
} catch (InterruptedException var4) {
if (this.mQuit) {
return;
}
}
}
//以下都是網絡請求隊列有網絡請求任務時執行
request.addMarker("network-queue-take");
if (request.isCanceled()) {//判斷是否取消
request.finish("network-discard-cancelled");
} else {
//網絡請求未取消
this.addTrafficStatsTag(request);
//處理網絡請求,得到NetworkResponse
NetworkResponse networkResponse = this.mNetwork.performRequest(request);
//標識請求完成
request.addMarker("network-http-complete");
if (networkResponse.notModified && request.hasHadResponseDelivered()) {
request.finish("not-modified");
} else {
//開始解析返回的結果,解析parseNetworkResponse可根據不同類型的方式進行解析,請看下圖:
Response<?> response = request.parseNetworkResponse(networkResponse);
//標識解析完成
request.addMarker("network-parse-complete");
//開始緩存請求結果,判斷是否可以緩存,默認可以
if (request.shouldCache() && response.cacheEntry != null) {
this.mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
//分發請求結果通過 mDelivery 完成
request.markDelivered();
this.mDelivery.postResponse(request, response);
}
}
}
解析 有Json
Image
String
等多種類型。
到此基本分析完畢。奉上一個整體流程圖,我在網上找到的,感覺還不錯: