Volley 異步網絡請求分析
Volley下載
Google I/O 2013 大會上發布的 Android 異步網絡請求框架和圖片加載框架。
試用場景:適合數據量小,通信頻繁的網絡操作。
git clone https://android.googlesource.com/platform/frameworks/volley
Volley架構
Volley Architect
如上官方給出的Volley架構圖,藍色為主線程,綠色為緩存線程,橙色是網絡線程。
總的來說,就是一個請求隊列和三種線程,UI線程(1個),Cache線程(1個)和Network線程(默認是4個)。
-
UI線程負責添加請求任務,執行任務結果;
-
Cache線程負責檢查緩存,命中后直接將任務結果分發到主線程;
-
Network線程由多個任務線程(NetworkDispatcher)組成的,相當于一個大小為size的線程池,這些線程會同時啟動,并持續的從任務隊列中獲取待執行的任務,任務執行完后會將結果分發到UI線程。
先簡介一下三個類的作用:
-
Volley.java:Volley對外暴露的主類,通過 newRequestQueue(…) 函數新建并啟動一個請求隊列RequestQueue。
-
Request:請求的抽象類。StringRequest、JsonRequest、ImageRequest 都是它的子類,表示某種類型的請求。可擴展性強。
-
RequestQueue.java:請求隊列,里面包含一個CacheDispatcher(用于處理走緩存請求的調度線程)、NetworkDispatcher數組(用于處理走網絡請求的調度線程),一個ResponseDelivery(返回結果分發接口),通過 start() 函數啟動時會啟動CacheDispatcher和NetworkDispatchers。
然后看創建請求隊列方法內的代碼:
public static RequestQueue newRequestQueue(Context context, HttpStack stack) { ... Network network = new BasicNetwork(stack); RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network); queue.start(); return queue; }
看到這里,需要了解三個類的作用:
-
HttpStack.java:處理HTTP請求,返回請求結果。目前Volley中有基于 HttpURLConnection 的 HurlStack 和 基于 Apache HttpClient 的HttpClientStack。
-
Network.java:調用HttpStack處理請求,并將結果轉換為可被ResponseDelivery處理的NetworkResponse。
-
Cache.java:緩存請求結果,Volley默認使用的是基于sdcard緩存的DiskBasedCache。NetworkDispatcher得到請求結果后判斷是否需要存儲在 Cache,CacheDispatcher會從 Cache 中取緩存結果。
創建Network需要HttpStatck,如果newRequestQueue傳入的stack為null,API Level >= 9,采用基于 HttpURLConnection 的 HurlStack;小于 9,采用基于 HttpClient 的 HttpClientStack。
if (stack == null) { if (Build.VERSION.SDK_INT >= 9) { stack = new HurlStack(); } else { // Prior to Gingerbread, HttpUrlConnection was unreliable. // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); } }
處理HTTP請求的HttpStatck也可以自定義,比如使用OKHTTP,具體可以參見我的另一篇文章使用OKHttp處理Volley的底層HTTP請求。
接下來啟動所需的所有線程:
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(); } }
-
CacheDispatcher.java:繼承自Thread,用于調度處理「緩存請求」。啟動后會不斷從緩存請求隊列中取請求處理,隊列為空則等待,請求處理結束則將結果傳遞給ResponseDelivery去執行后續處理。當結果未緩存過、緩存失效或緩存需要刷新的情況下,該請求都需要重新進入NetworkDispatcher去調度處理。
-
NetworkDispatcher.java:繼承自Thread,用于調度處理「網絡請求」。啟動后會不斷從網絡請求隊列中取請求處理,隊列為空則等待,請求處理結束則將結果傳遞給ResponseDelivery去執行后續處理,并判斷結果是否要進行緩存。
-
ResponseDelivery.java:分發結果的interface,postResponse以及postError。
接下來再回頭看一下Volley的架構圖。
-
第一步:把請求加入緩存隊列
-
第二步:「緩存調度線程」CacheDispatcher從緩存隊列中取出一個請求,如果緩存命中,就讀取緩存響應并解析,然后將結果返回到主線程
-
第三步:緩存未命中,請求被加入網絡請求隊列,「網絡調度線程」NetworkDispatcher輪詢取出請求,HTTP請求傳輸,解析響應,寫入緩存,然后將結果返回到主線程