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

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

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,這兩個參數就是主要的成員變量。socket

 /**
     * 帶一個默認大小的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接口同名的方法,這纔是真正執行請求的方法,也是直接傳入請求返回響應。ide

而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作出各類判斷。ui

B:而後再把httpResponse的Entity轉化爲ByteArray,並處理各類發生的異常。this

C:最後的過程是這樣的:經過Volley建立一個RequestQueue請求隊列,當這個隊列開始運做的時候會啓動NetworkDispatcher這個工做線程,而BasicNetwork的performRequest()的方法就在NetworkDispatcher線程run()方法中調用,而後經過mHttpStack的performRequest()方法獲取一個networkResponse,在NetworkDispatcher線程把這個networkResponse轉化爲指望的數據類型,好比Response<String>,Response<Json>,Response<Bitmap>。

相關文章
相關標籤/搜索