Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中關於Volley的使用(六)認識 CacheDispatcher

Android中關於Volley的使用(六)認識 CacheDispatcher

編輯:關於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;
            }
        }
    }

緩存線程(CacheDispatcher)主要做了幾件事情:

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;

3)判斷請求是否已經取消,如果已經被取消了,則不需要再走下去。

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。

結束!


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved