Volley源碼個人分析

一直看源碼也是記不住,總是忘記,希望通過博客可以給自己留存一些記憶。

我從入口開始分析,創建一個請求隊列,通過Volley的靜態方法newRequestQueue新建,然後將請求添加至請求隊列即可。

RequestQueue mRequestQueue = Volley.newRequestQueue(context);
mRequestQueue.add(request);

可以通過mRequestQueue的cancelAll方法取消所有TAG請求。

 @Override
    protected void onDestroy() {
        super.onDestroy();
        mRequestQueue.cancelAll(TAG);
    }

接着用一個最簡單的請求方式,作爲示例看一下請求的參數

StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
            // TODO
                Log.e(TAG, response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
            // TODO
                error.printStackTrace();
            }
        });

第一個參數,是一個請求方式,一共有GET,POST,PUT,DELETE,HEAD,OPTIONS,TRACE,PATCH八種方式。
第二個參數,是請求的網絡地址url。
第三個參數,是請求返回的響應結果的回調。
第四個參數,是請求返回的錯誤響應的回調。

以上是一個大概的使用過程,通過這個過程進行分析。

首先,請求隊列的創建調用了Volley的newRequestQueue靜態方法,跟進去之後發現最終調用了一個含有多個參數的newRequestQueue靜態方法。

RequestQueue queue = new RequestQueue(cache==null?new DiskBasedCache(cacheDir):cache, network);
queue.start();

這個方法裏new出一個請求隊列,請求隊列的構造方法需要兩個參數,一個緩存,一個網絡任務。構造方法沒什麼說可說的了,就是初始化一些成員變量。創建隊列的目的是爲了處理請求,所以調用了start方法。

    /**
     * Starts the dispatchers in this queue.
     */
    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();
        }
    }

start方法裏很簡單,是新建了一個調度緩存的線程和一個調度網絡任務的線程數組,並將所有線程調用start方法啓動。接下來,就要去看看線程裏的run方法了。
先看看CacheDispatcher的run方法,去除掉我認爲不影響流程的代碼,剩餘的部分就是說,不斷的從緩存隊列裏取任務請求。如果緩存中沒有或者已經過期了,就將請求添加至網絡請求隊列。最後如果緩存中存在的話,就去處理響應結果並解析。


    @Override
    public void run() {

        ······

        while (true) {

                // Get a request from the cache triage queue, blocking until
                // at least one is available.
                final Request<?> request = mCacheQueue.take();
                request.addMarker("cache-queue-take");

                ···

                // Attempt to retrieve this item from cache.
                Cache.Entry entry = mCache.get(request.getCacheKey());
                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");

                ···

        }
    }

再看看NetworkDispatcher的run方法,也是有個while死循環,不斷的從請求隊列裏取任務請求。然後通過Network的performRequest方法處理請求,返回響應結果。然後對響應結果進行解析,最後,判斷一下是否添加至緩存中,若條件滿足,則將請求添加至緩存,方便下次進行快速讀取。


    @Override
    public void run() {

        while (true) {

            Request<?> request;

                // Take a request from the queue.
                request = mQueue.take();

                ······

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

                ······

                // 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");
                }
            ···
        }
    }

若問請求哪裏來?答:通過請求隊列的add方法添加。就是最前面提到的mRequestQueue.add(request);

以上就是Volley源碼閱讀的大概一個過程,無需在意太多的細節,這是我總結出的閱讀源碼的經驗。當然,經驗有限,目前也只能寫成這樣。

在前進的道路上,跟隨一些大神的腳步是必不可免的。爲了加強理解,更多細節可以看看Volley源碼解析

發佈了28 篇原創文章 · 獲贊 27 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章