谷歌Volley網絡框架講解——Network及其實現類


我們看到Network接口只有一個實現類BasicNetwork,而HttpStack有兩個實現類。

BasicNetwork這個類是toolbox工具箱包里的,實現了Network接口。

先來看下Network這個interface,performRequest(Request*)執行一個請求,以一個Request為參數,返回一個

NetworkResponse 。
public interface Network {
    /**
     * Performs the specified request.執行這個請求
     * @param request Request to process//待處理的請求
     * @return A {@link NetworkResponse} with data and caching metadata; will never be null
     * 返回一個請求結果,不會為空
     * @throws VolleyError on errors
     */
    public NetworkResponse performRequest(Request<?> request) throws VolleyError;
}

BasicNetwork實現了Network接口,我們來看下UML圖。

再來看下它的構造函數,兩個參數HttpStack和ByteArrayPool,這兩個參數就是主要的成員變量。

 /**
     * 帶一個默認大小的ByteArrayPool緩沖池
     * @param httpStack HTTP stack to be used
     */
    public BasicNetwork(HttpStack httpStack) {
        // If a pool isn't passed in, then build a small default pool that will give us a lot of
        // benefit and not use too much memory.
        //如果一個池沒有通過,將建立一個小的默認緩存池,這樣會給我們帶來很大的益處,不需要耗費很多內存
        this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE));
    }

    /**
     * 主構造方法BasicNetwork(HttpStack*,ByteArrayPool*)
     * @param httpStack HTTP stack to be used
     * @param pool a buffer pool that improves GC performance in copy operations
     */
    public BasicNetwork(HttpStack httpStack, ByteArrayPool pool) {
        mHttpStack = httpStack;
        mPool = pool;
    }

再看看哪個方法用到了mHttpStack,就是在實現Network接口的performRequest()方法,並且mHttpStack有個跟Network接口同名的方法,這才是真正執行請求的方法,也是直接傳入請求返回響應。

而mPool是在entityToBytes()這個方法中用到,顧名思義這個方法就是把HttpEntity轉換為bytes數據,而這個緩存池就是為便捷轉換數據格式。

再詳細看下最重要的方法performRequest(),代碼中均以加上注釋,見解有誤望讀者們見諒和請教。

/**
     * @title performRequest執行各種Request請求並以NetworkResponse的形式返回結果
     * @param Request
     * @return NetworkResponse
     * @throws VolleyError
     * 定義:{@link Network#performRequest(Request)}
     * 被調:{@link NetworkDispatcher#run()}
     * 
     */
    @Override//NetworkDispatcher的run()方法中調用
    public NetworkResponse performRequest(Request<?> request) throws VolleyError {
        long requestStart = SystemClock.elapsedRealtime();//開始請求時間
        while (true) {
            HttpResponse httpResponse = null;//apache的請求結果
            byte[] responseContents = null;//請求的內容
            Map<String, String> responseHeaders = new HashMap<String, String>();//響應結果頭部信息
            try {
                // Gather headers.
                Map<String, String> headers = new HashMap<String, String>();//保存緩存數據
                addCacheHeaders(headers, request.getCacheEntry());//先獲取緩存數據
                httpResponse = mHttpStack.performRequest(request, headers);//去調用mHttpStack的實現方法執行請求
                StatusLine statusLine = httpResponse.getStatusLine();//獲取http狀態線
                int statusCode = statusLine.getStatusCode();//獲取狀態碼

                responseHeaders = convertHeaders(httpResponse.getAllHeaders());
                // Handle cache validation.//處理緩存驗證
                if (statusCode == HttpStatus.SC_NOT_MODIFIED) {//返回緩存數據
                    return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
                            request.getCacheEntry().data, responseHeaders, true);
                }

                //把HttpEntity轉化為byte[]數據
                responseContents = entityToBytes(httpResponse.getEntity());
                // if the request is slow, log it.//如果請求很慢,就打印出來看一下
                long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
                logSlowRequests(requestLifetime, request, responseContents, statusLine);//打印

                //連接正常但是返回無內容,拋出IO異常
                if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_NO_CONTENT) {
                    throw new IOException();
                }
                return new NetworkResponse(statusCode, responseContents, responseHeaders, false);
            } catch (SocketTimeoutException e) {//讀取超時,重試
                attemptRetryOnException("socket", request, new TimeoutError());
            } catch (ConnectTimeoutException e) {//連接超時,重試
                attemptRetryOnException("connection", request, new TimeoutError());
            } catch (MalformedURLException e) {//Bad URL
                throw new RuntimeException("Bad URL " + request.getUrl(), e);
            } catch (IOException e) {//IO異常
                int statusCode = 0;
                NetworkResponse networkResponse = null;
                if (httpResponse != null) {
                    statusCode = httpResponse.getStatusLine().getStatusCode();
                } else {//如果沒有返回httpResponse,就說明沒連接
                    throw new NoConnectionError(e);
                }
                VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
                if (responseContents != null) {//返回數據不為空
                    networkResponse = new NetworkResponse(statusCode, responseContents,
                            responseHeaders, false);//創建響應體
                    if (statusCode == HttpStatus.SC_UNAUTHORIZED ||
                            statusCode == HttpStatus.SC_FORBIDDEN) {//認證失敗異常,重試
                        attemptRetryOnException("auth",
                                request, new AuthFailureError(networkResponse));
                    } else {//服務器異常
                        // TODO: Only throw ServerError for 5xx status codes.
                        throw new ServerError(networkResponse);//只有狀態碼為5XX才拋出服務器異常
                    }
                } else {//網絡異常
                    throw new NetworkError(networkResponse);
                }
            }
        }
    }

A:先是通過mHttpStack把請求執行並且獲取它的響應結果,根據HttpStatus做出各種判斷。

B:然后再把httpResponse的Entity轉化為ByteArray,並處理各種發生的異常。

C:最后的過程是這樣的:通過Volley創建一個RequestQueue請求隊列,當這個隊列開始運作的時候會啟動NetworkDispatcher這個工作線程,而BasicNetwork的performRequest()的方法就在NetworkDispatcher線程run()方法中調用,然后通過mHttpStack的performRequest()方法獲取一個networkResponse,在NetworkDispatcher線程把這個networkResponse轉化為期望的數據類型,比如Response<String>,Response<Json>,Response<Bitmap>。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM