Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中關於Volley的使用(七)認識 NetworkDispatcher 和 BasicNetwork

Android中關於Volley的使用(七)認識 NetworkDispatcher 和 BasicNetwork

編輯:關於Android編程

Volley最主要的功能其實就是跟網絡打交道,然後從網絡中獲取相對應的數據,雖然有緩存線程(CacheDispatcher),但是如果緩存中沒有對應的記錄的話,還是會將其扔到網絡隊列中,由網絡線程(NetworkDispatcher)來干活。

那麼就看看NetworkDispatcher都干什麼吧,如下:

    public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        Request request;
        while (true) {
            try {
                // 從隊列中獲取一個請求,如果沒有請求,則會一直阻塞
                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 (request.isCanceled()) {
                    request.finish("network-discard-cancelled");
                    continue;
                }

                addTrafficStatsTag(request);

                // 調用mNetwork去跟網絡打交道
                NetworkResponse networkResponse = mNetwork.performRequest(request);
                request.addMarker("network-http-complete");

                // 如果服務器返回一個未修改(304)的響應,並且這個請求已經發送過響應對象,不需要再繼續,因為沒改過
                if (networkResponse.notModified && request.hasHadResponseDelivered()) {
                    request.finish("not-modified");
                    continue;
                }

                // 分析響應的數據,返回Response對象
                Response response = request.parseNetworkResponse(networkResponse);
                request.addMarker("network-parse-complete");

                // 根據request的shouldCache字段來判斷是不是需要緩存,如果需要,則將其放到mCache中。
                if (request.shouldCache() && response.cacheEntry != null) {
                    mCache.put(request.getCacheKey(), response.cacheEntry);
                    request.addMarker("network-cache-written");
                }

                // 調用 mDelivery將Response對象傳回主線程進行UI的更新。
                request.markDelivered();
                mDelivery.postResponse(request, response);
            } catch (VolleyError volleyError) {
                parseAndDeliverNetworkError(request, volleyError);//有錯誤,也會調用到mDelivery,將錯誤信息傳回到主線程,進行提示
            } catch (Exception e) {
                VolleyLog.e(e, "Unhandled exception %s", e.toString());
                mDelivery.postError(request, new VolleyError(e));
            }
        }
    }
網絡線程(NetworkDispatcher)主要做了幾件事情:

1)調用 mQueue的take()方法從隊列中獲取請求,如果沒有請求,則一直阻塞在那裡等待,直到隊列中有新的請求到來。

2)判斷請求有沒有被取消,如果被取消,則重新獲取請求。

3)調用Network對象將請求發送到網絡中,並返回一個 NetworkResponse對象。

4)調用請求的pareseNetworkResonse方法,將NetworkResponse對象解析成相對應的Response對象。

5)判斷請求是否需要緩存,如果需要緩存,則將其Response中cacheEntry對象放到緩存mCache中。

6)調用 mDelivery將Response對象傳到主線程中進行UI更新。

另外有一個要注意的就是,在Volley中,默認是有4個網絡線程同時在跑的,而對應的緩存線程,則只有一個。

從上面的代碼中,可以看到,網絡線程其實是調用 Network對象去實現跟網絡進行溝通的,而在Volley中,默認的Network實現類,則是BasicNetwork類。

下面我們就看看它的performRequest方法:

   public NetworkResponse performRequest(Request request) throws VolleyError {
        ...
        while (true) {
            HttpResponse httpResponse = null;
            byte[] responseContents = null;
            Map responseHeaders = new HashMap();
            try {
                // 添加頭部信息
                Map headers = new HashMap();
                addCacheHeaders(headers, request.getCacheEntry());
                httpResponse = mHttpStack.performRequest(request, headers);//調用HttpStack對象去網絡中獲取數據
                StatusLine statusLine = httpResponse.getStatusLine();
                int statusCode = statusLine.getStatusCode();

                responseHeaders = convertHeaders(httpResponse.getAllHeaders());
                // 從響應的狀態行獲取狀態編碼,如果是304(未修改),說明之前已經取過數據了,那麼就直接利用緩存中的數據,構造一個NetworkResonse對象
                if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
                    return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
                            request.getCacheEntry() == null ? null : request.getCacheEntry().data,
                            responseHeaders, true);
                }

                // 有些響應是不帶內容的,比如響應狀態編碼是204的話,添加一個空的byte作為內容,後面好統一處理。
                if (httpResponse.getEntity() != null) {
                  responseContents = entityToBytes(httpResponse.getEntity());
                } else {
                  // Add 0 byte response as a way of honestly representing a
                  // no-content request.
                  responseContents = new byte[0];
                }
                ...//忽略了一些log的處理。
                return new NetworkResponse(statusCode, responseContents, responseHeaders, false);
            } ...//這裡忽略了一些異常處理
            } catch (IOException e) {
                ...
                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));//這裡會根據Volley的Retyr機制進行重新獲取。
                    } else {
                        throw new ServerError(networkResponse);
                    }
                } else {
                    throw new NetworkError(networkResponse);
                }
            }
        }
    }

BasicNetwork做的事情如下:

1)對於已經有緩存的請求,添加其頭部信息,如下:

    private void addCacheHeaders(Map headers, Cache.Entry entry) {
        // If there's no cache entry, we're done.
        if (entry == null) {
            return;
        }

        if (entry.etag != null) {
            headers.put("If-None-Match", entry.etag);
        }

        if (entry.serverDate > 0) {
            Date refTime = new Date(entry.serverDate);
            headers.put("If-Modified-Since", DateUtils.formatDate(refTime));
        }
    }

2)調用 HttpStack 對象去網絡中獲取數據,返回httpResonse 對象。

3)根據狀態編碼來返回不同的Response對象,如304(未修改)就返回緩存中的數據,如果不是,則根據響應中的數據,重新構造一個NetworkResponse對象。

4)BasicNetwork實現了重試的機制,如果第一次從網絡獲取失敗,默認會重新再嘗試一次,如果失敗,則會將Error返回,默認的實現類是DefaultRetryPolicy類。


在Network中返回的NetworkResponse對象,會在NetworkDispatcher中由具體的Request(比如ImageRequest,JsonRequest)類來進行解析,再最後返回給UI線程。

結束!

關於緩存線程的介紹:

Android中關於Volley的使用(六)認識 CacheDispatcher

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved