天天看點

Volley源碼解析<五> CacheDispatcher和NetworkDispatcherVolley源碼解析<五> CacheDispatcher和NetworkDispatcher

Volley源碼解析<五> CacheDispatcher和NetworkDispatcher

@[Volley, 排程器, CacheDispatcher, NetworkDispatcher]

聲明:轉載請注明出處,知識有限,如有錯誤,請多多交流指正!

  • Volley源碼解析五 CacheDispatcher和NetworkDispatcher
      • 結構
      • CacheDispatcher
      • NetworkDispatcher

結構

Volley源碼解析&lt;五&gt; CacheDispatcher和NetworkDispatcherVolley源碼解析&lt;五&gt; CacheDispatcher和NetworkDispatcher

主要通過RequestQueue調用start()方法啟動CacheDispatcher和NetworkDispatcher線程

CacheDispatcher

1. 構造方法

CacheDispatcher繼承自Thread,當被start後就執行它的run方法,在RequestQueue.add方法中,如果使用緩存直接就将Request放入緩存隊列mCacheQueue中了,使用mCacheQueue的位置就是CacheDispatcher,CacheDispatcher的構造函數中傳入了緩存隊列mCacheQueue、網絡隊列mNetworkQueue、緩存對象mCache及結果派發器mDelivery

public CacheDispatcher(BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue, Cache cache, ResponseDelivery delivery) {
        mCacheQueue = cacheQueue;
        mNetworkQueue = networkQueue;
        mCache = cache;
        mDelivery = delivery;
    }
           

其中

cacheQueue:緩存請求隊列,就是RequestQueue中的mCacheQueue

networkQueue:網絡請求隊列,就是RequestQueue中的mNetworkQueue

cache:儲存緩存資料,就是RequestQueue中的mCache

delivery:用于分發響應結果,就是RequestQueue中的mDelivery

2. 主要運作方法run()

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();

        Request<?> request;
        while (true) {
            // release previous request object to avoid leaking request object when mQueue is drained.
            request = null;
            try {
                // Take a request from the queue.
                // 從緩存隊列中取出請求
                request = mCacheQueue.take();
            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    return;
                }
                continue;
            }
            try {
                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());

                //緩存已過期(包括expired與Soft-expired)

                // 無緩存資料,則加入網絡請求
                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.
                    // 緩存沒有Soft-expired,則直接通過mDelivery将解析好的結果傳遞給請求發起者
                    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.
                    final Request<?> finalRequest = request;
                    //需要重新整理,那麼就再次送出網絡請求...擷取伺服器的響應...
                    mDelivery.postResponse(request, response, new Runnable() {
                        @Override
                        public void run() {
                            try {
                                // 網絡來更新請求響應
                                mNetworkQueue.put(finalRequest);
                            } catch (InterruptedException e) {
                                // Not much we can do about this.
                            }
                        }
                    });
                }
            } catch (Exception e) {
                VolleyLog.e(e, "Unhandled exception %s", e.toString());
            }
        }
    }
           

3. 其他

//用于判斷線程是否結束,用于退出線程
private volatile boolean mQuit = false;

//出線程
public void quit() {
    mQuit = true;
    interrupt();
}
           

在run方法中一直運作着

while (true)

,那麼是如何停止線程的呢?當通過調用

quit

方法中

interrupt()

時,會

InterruptedException

異常退出線程

NetworkDispatcher

1. 構造方法

原理和

CacheDispatcher

基本上一樣的,主要用于網絡請求

public NetworkDispatcher(BlockingQueue<Request<?>> queue, Network network, Cache cache, ResponseDelivery delivery) {
        mQueue = queue;
        mNetwork = network;
        mCache = cache;
        mDelivery = delivery;
    }
           

其中

queue:網絡請求隊列,就是RequestQueue中的mNetworkQueue

network:網絡請求封裝類,就是BasicNetwork

cache:儲存緩存資料,就是RequestQueue中的mCache

delivery:用于分發響應結果,就是RequestQueue中的mDelivery

2. 主要運作方法run()

public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

        Request<?> request;
        while (true) {
            long startTimeMs = SystemClock.elapsedRealtime();
            // release previous request object to avoid leaking request object when mQueue is drained.
            request = null;
            try {
                // Take a request from the queue.
                request = mQueue.take();
            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    return;
                }
                continue;
            }

            try {
                request.addMarker("network-queue-take");

                // If the request was cancelled already, do not perform the
                // network request.
                // 如果請求被中途取消
                if (request.isCanceled()) {
                    request.finish("network-discard-cancelled");
                    continue;
                }

                // 流量統計用的
                addTrafficStatsTag(request);

                // Perform the network request.
                // 請求資料
                NetworkResponse networkResponse = mNetwork.performRequest(request);
                request.addMarker("network-http-complete");

                // If the server returned 304 AND we delivered a response already,
                // we're done -- don't deliver a second identical response.
                if (networkResponse.notModified && request.hasHadResponseDelivered()) {
                    //如果是相同的請求,那麼伺服器就傳回一次響應
                    request.finish("not-modified");
                    continue;
                }

                // Parse the response here on the worker thread.
                // 解析響應資料
                Response<?> response = request.parseNetworkResponse(networkResponse);
                request.addMarker("network-parse-complete");

                // Write to cache if applicable.
                // TODO: Only update cache metadata instead of entire record for 304s.
                if (request.shouldCache() && response.cacheEntry != null) {
                    // 緩存資料
                    mCache.put(request.getCacheKey(), response.cacheEntry);
                    request.addMarker("network-cache-written");
                }

                // Post the response back.
                //确認請求要被分發
                request.markDelivered();

                //發送請求
                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);
            }
        }
    }
           

繼續閱讀