Volley學習(RequestQueue分析),volleyrequestqueue

來源:互聯網
上載者:User

Volley學習(RequestQueue分析),volleyrequestqueue

      Volley的RequestQueue用來緩衝要求處理常式CacheDispatch和網路要求處理常式NetworkDispatch來處理Request的。當我們調用RequestQueue.start()是,兩個處理器開始運行起來,等待Request的到來。

       

 public void start() {        stop();  // Make sure any currently running dispatchers are stopped.        // Create the cache dispatcher and start it.        mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);        mCacheDispatcher.start();        // Create network dispatchers (and corresponding threads) up to the pool size.        for (int i = 0; i < mDispatchers.length; i++) {            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,                    mCache, mDelivery);            mDispatchers[i] = networkDispatcher;            networkDispatcher.start();        }    }

  Volley先讀緩衝然後,沒有cache hit的話再從網路上擷取,所以先啟動CacheDispatcher,然後啟動NetworkDispatcher。不過在啟動處理器前先調用stop()函數清除掉以前RequestQueue裡的到期的Dispatcher(Dispatcher都是繼承Thread)。以防影響效能。Volley啟動一個CacheDispatcher和4個NetworkDispatcher,之所以這樣設計,個人人為是主要考慮到網狀圖片的下載,所以利用多個NetworkDispatcher來處理網路請求。然後看一下stop()函數。

   

   public void stop() {        if (mCacheDispatcher != null) {            mCacheDispatcher.quit();        }        for (int i = 0; i < mDispatchers.length; i++) {            if (mDispatchers[i] != null) {                mDispatchers[i].quit();            }        }    }

   調用Dispatcher的quit()函數來結束線程。以NetworkDispatcher.quit()為例:

 public void quit() {        mQuit = true;        interrupt();    }

  函數將mQuit變數置為true。為什麼要這樣做,因為在networkdispatcher線程中的中斷異常處理中,判斷mQuit的值,如果真,則退出迴圈,結束線程。否則continue,繼續從Queue中去取Request處理。

 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;            }

  接下來,看下RequestQueue的add函數。

   

 public Request add(Request 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.        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) {            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);                if (VolleyLog.DEBUG) {                    VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);                }            } else {                // Insert 'null' queue for this cacheKey, indicating there is now a request in                // flight.                mWaitingRequests.put(cacheKey, null);                mCacheQueue.add(request);            }            return request;        }    }

  首先將Request加入到mCurrentRequests中,因為存在多個線程競爭的問題,在這個代碼塊上進行了同步。然後request.setSequence().為當前Request分配一個序號,為什麼這樣做,因為我們下面要將Request放到NetworkQueue中或者CacheQueue中,這兩個隊列都是PriorityBlockingQueue,裡面的元素是根據自訂的權重來排序的。PriorityBlockingQueue裡的元素須實現Comparable介面,來看下我們這裡的Requeset的實現:

    

 @Override    public int compareTo(Request<T> other) {        Priority left = this.getPriority();        Priority right = other.getPriority();        // High-priority requests are "lesser" so they are sorted to the front.        // Equal priorities are sorted by sequence number to provide FIFO ordering.        return left == right ?                this.mSequence - other.mSequence :                right.ordinal() - left.ordinal();    }

  Request的策略是現根據每個Request的Priority來判斷,如果兩個Request的Priority相同,那麼載根據兩個Request的Sequence來進行判斷隊列裡的先後順序。

     

1 public enum Priority {2 LOW,3 NORMAL,4 HIGH,5 IMMEDIATE6 }View Code

  

     給當前Request加上序列後,判斷一下當前Request是否需要緩衝,如果不需要則直接把Request加入到NetworkQueue隊列裡。如果需要緩衝,取出Request的緩衝鍵,從mWaitingRequests裡看下有沒有Request的緩衝鍵.在RequestQueue中有四個隊列。mCurrentRequests,mWaitingRequests,mCacheQueue,mNetworkQueue。每當一個請求到來時,先加入到mCurrentRequests,然後判斷當前Request是否需要緩衝,如果不用緩衝的Request,則直接加入到mNetworkQueue隊列中等待網路處理器(NetWorkDispatcher)去處理。如果需要緩衝的話,根據Request擷取相應的cacheKey,如果cacheKey不存在的話,說明這個需要緩衝的Request是第一次請求。那麼將cacheKey放入到mWaitingRequests隊列裡。(這裡插播一下,mCurrentRequests存放的是所有交由RequestQueue處理的Request,mWaitingRequests裡存放的是mCacheQueue裡已經有相同url的Request,mWatiingRequests的出現就是為了避免不必要的網路資料擷取),並將Request放入到mCacheQueue中以做處理。

1 // Insert 'null' queue for this cacheKey, indicating there is now a request in2 // flight.3 mWaitingRequests.put(cacheKey, null);4 mCacheQueue.add(request);View Code

 

    如果cacheKey存在的話,說明已經有相同的Request正在處理(這裡的cacheKey是通過getUrl()得到的,也就是建立Request時的url)。這時將此Request放入到mWaitingRequest隊列中等待In-flight Request的處理結果。

    add完然後看finish(Request req);

1 void finish(Request request) { 2 // Remove from the set of requests currently being processed. 3 synchronized (mCurrentRequests) { 4 mCurrentRequests.remove(request); 5 } 6 7 if (request.shouldCache()) { 8 synchronized (mWaitingRequests) { 9 String cacheKey = request.getCacheKey();10 Queue<Request> waitingRequests = mWaitingRequests.remove(cacheKey);11 if (waitingRequests != null) {12 if (VolleyLog.DEBUG) {13 VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.",14 waitingRequests.size(), cacheKey);15 }16 // Process all queued up requests. They won't be considered as in flight, but17 // that's not a problem as the cache has been primed by 'request'.18 mCacheQueue.addAll(waitingRequests);19 }20 }21 }22 }View Code

     首先先從mCurrentRequests集合中remove掉當前Request,然後在mWaitingRequests中去掉當前的Request.然後將此Request對應的mWaitingRequest中儲存的Request放到mCacheQueue中等待處理(因為此時對應的url的網路資料已經載入到本地,所以這些mWaitingRequests裡的Request被處理時直接從本地解析,不用耗時的網路擷取一遍)。

    RequestQueue類中還有一個CancelAll()函數,它的作用是根據指定的Request tag來刪除響應的Request.

    public void cancelAll(RequestFilter filter) {        synchronized (mCurrentRequests) {            for (Request<?> request : mCurrentRequests) {                if (filter.apply(request)) {                    request.cancel();                }            }        }    }    /**     * Cancels all requests in this queue with the given tag. Tag must be non-null     * and equality is by identity.     */    public void cancelAll(final Object tag) {        if (tag == null) {            throw new IllegalArgumentException("Cannot cancelAll with a null tag");        }        cancelAll(new RequestFilter() {            @Override            public boolean apply(Request<?> request) {                return request.getTag() == tag;            }        });    }

  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.