編輯:關於Android編程
當調用 RequestQueue的 add()方法添加 Request 的時候,會根據請求的一個參數 shouldCache,來判斷要不要去緩存中查詢,如果是去緩存中查詢,那麼就會把請求放到CacheQueue中,如下:
mWaitingRequests.put(cacheKey, null); mCacheQueue.add(request);
這個時候,線程CacheDispatcher其實已經在跑了,到它的run方法中來看一下:
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; } // 根據request的cacheKey從緩存中得到對應的記錄 Cache.Entry entry = mCache.get(request.getCacheKey()); if (entry == null) { request.addMarker("cache-miss"); // 這裡說明緩存中沒有對應的記錄,那麼需要去網絡中獲取,那麼就將它放到Network的隊列中 mNetworkQueue.put(request); continue; } // 如果緩存中有記錄,但是已經過期了或者失效了,也需要去網絡獲取,放到Network隊列中 if (entry.isExpired()) { request.addMarker("cache-hit-expired"); request.setCacheEntry(entry); mNetworkQueue.put(request); continue; } // 如果上面的情況都不存在,說明緩存中存在這樣記錄,那麼就調用request的parseNetworkResponse方法,獲取一個響應Response request.addMarker("cache-hit"); Response> response = request.parseNetworkResponse( new NetworkResponse(entry.data, entry.responseHeaders)); request.addMarker("cache-hit-parsed"); if (!entry.refreshNeeded()) { // 緩存記錄,不需要更新,那麼就直接調用mDelivery,傳回給主線程去更新。 mDelivery.postResponse(request, response); } else { // 還存在這樣一種情況,緩存記錄存在,但是它約定的生存時間已經到了(還未完全過期,叫軟過期),可以將其發送到主線程去更新 // 但同時,也要從網絡中更新它的數據 request.addMarker("cache-hit-refresh-needed"); request.setCacheEntry(entry); // Mark the response as intermediate. response.intermediate = true; // 將其傳回主線程的同時,將請求放到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; } continue; } } }
1)初始化本地緩存
2)開始一個無限的循環,調用 mCacheQueue的take方法,來獲得一個請求,而mCacheQueue是一個BlockingQueue,也就是說,當隊列中沒有請求的時候,take方法就會一直阻塞在這裡,等待隊列中的請求,而一旦隊列中有新的請求進來了,那麼它就會馬上執行下去。
/** The queue of requests coming in for triage. */ private final BlockingQueue> mCacheQueue; /** The queue of requests going out to the network. */ private final BlockingQueue > mNetworkQueue;
4)根據請求的CacheKey去緩存中尋找相對應的記錄,如果找不到對應的記錄,或者對應的記錄過期了,則將其放到NetworkQueue隊列中。
5)緩存中存在相對應的記錄,那麼調用每個請求具體的實現方法 parseNetworkResponse函數,根據具體的請求去解析得到對應的響應Response對象。
6)獲得Response對象之後,還會再進行判斷這個請求是不是進行一次網絡的更新,這是根據記錄的soft-ttl (time-to-live)屬性,如下:
/** True if the entry is expired. */ public boolean isExpired() { return this.ttl < System.currentTimeMillis(); } /** True if a refresh is needed from the original data source. */ public boolean refreshNeeded() { return this.softTtl < System.currentTimeMillis(); }
從這裡也可以看到,expired的判斷跟refreshNeed的判斷是兩個字段,一個是ttl,一個是softTtl。
如果需要進行更新,那麼就會在發送響應結果回主線程更新的同時,再將請求放到NetworkQueue中,從網絡中更新請求對應的數據。如果不需要,則直接將結果調用mDelivery傳回主線程進行UI的更新。
CacheDispatcher做的事情並不多,因為Volley主要的功能其實還是跟網絡打交道,所以主要的實現,其實還是NetworkDispatcher。
結束!
前言 高效的設計稿標注及測量工具Markman介紹。最近有個煩惱是UI設計師可能太忙了,經常給出的UI設計稿中有很多地方都沒有標注,比如長度和顏色值等。這個時候每次都要通
最近在學自定義View,無意中看到鴻洋大神以前寫過的2048,看起來很不錯,所以自己在他的基礎上做一個加強版的2048。先看圖: 功能除了正常的2048外,還支
iMAG是一個非常簡潔高效的移動跨平台開發框架,開發一次可以同時兼容Android和iOS平台,有點兒Web開發基礎就能很快上手。當前移動端跨平台開發的框架有很多,但用i
其實對於apk包的安裝,4.4和之前版本沒大的差別。Android中app安裝主要有以下幾種情況:系統啟動時安裝,adb命令安裝,Google