編輯:關於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; MapresponseHeaders = 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); } } } }
1)對於已經有緩存的請求,添加其頭部信息,如下:
private void addCacheHeaders(Mapheaders, 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)); } }
3)根據狀態編碼來返回不同的Response對象,如304(未修改)就返回緩存中的數據,如果不是,則根據響應中的數據,重新構造一個NetworkResponse對象。
4)BasicNetwork實現了重試的機制,如果第一次從網絡獲取失敗,默認會重新再嘗試一次,如果失敗,則會將Error返回,默認的實現類是DefaultRetryPolicy類。
在Network中返回的NetworkResponse對象,會在NetworkDispatcher中由具體的Request(比如ImageRequest,JsonRequest)類來進行解析,再最後返回給UI線程。
結束!
關於緩存線程的介紹:
Android中關於Volley的使用(六)認識 CacheDispatcher
前言本文是通過閱讀各種文章及代碼,總結出來的,其中難免有些地方理解得不對,歡迎大家批評指正。顯示系統基礎知識定義在一個典型的顯示系統中,一般包括CPU、GPU、displ
一、簡介上篇博客概括的介紹了硅谷商城項目的分類模塊技術要點。本篇內容給大家講解硅谷商城項目發現模塊,發現模塊用的技術包括:采用TabLayout實現標題的切換、采用Ope
Activity是Android系統的4個應用程序組件之一。通過傳統方法顯示的Activity都是充滿整個屏幕,也就是全屏的Activity。事實上,Activity不僅
學習目的: 1、掌握在Android中如何建立Button 2、掌握Button的常用屬性 3、掌握Button按鈕的點擊事件(監聽器) Button是各種UI中最常用的