前言
Volley是什么鬼?
Volley是谷歌提出的網(wǎng)絡(luò)通信框架,該框架封裝了網(wǎng)絡(luò)通信和圖片加載,使得使用起來(lái)更加的簡(jiǎn)單快捷。
為什么要使用Volley?
- 基本的網(wǎng)絡(luò)通信框架中,底層實(shí)際都封裝了兩種通信方式:HttpUrlConnectTion和HttpClient。這兩種方式實(shí)現(xiàn)比較復(fù)雜,因此,AsyncHttpClient底層封裝了具體的通信方式,而只將接口暴露給用戶,用戶使用起來(lái)十分的方便。
- universal-imageLoader,則將重心放在圖片加載,以及圖片資源清除等。
這兩種框架功能較為細(xì)化,因此則顯得過(guò)于單一。因此google公司發(fā)布了Volley這個(gè)框架,既滿足了網(wǎng)絡(luò)通信的簡(jiǎn)單化,又具有了圖片加載的功能,同時(shí),增加了自定義的功能,用戶可以對(duì)該框架進(jìn)行擴(kuò)展來(lái)滿足自己的項(xiàng)目需求。
源代碼解析##
請(qǐng)求架構(gòu)圖###
RequestQueue會(huì)維護(hù)一個(gè)緩存調(diào)度線程和網(wǎng)絡(luò)調(diào)度線程。當(dāng)一個(gè)請(qǐng)求被加入到隊(duì)列中后,首先由緩存線程來(lái)對(duì)該請(qǐng)求進(jìn)行篩選,如果該請(qǐng)求的內(nèi)容在緩存中可以找得到話,則緩存線程會(huì)來(lái)解析緩存內(nèi)容,并將解析的內(nèi)容分發(fā)到主線程;如果緩存中沒(méi)有相關(guān)的內(nèi)容時(shí),則緩存調(diào)度線程會(huì)將該請(qǐng)求移交給網(wǎng)絡(luò)調(diào)度線程中的通信隊(duì)列中,該線程依次取出隊(duì)列中的請(qǐng)求,發(fā)起http請(qǐng)求,得到回應(yīng)后,將返回的數(shù)據(jù)進(jìn)行解析,并寫(xiě)入緩存中,同時(shí)將該內(nèi)容分發(fā)給主線程。
具體源碼流程分析###
Volley.newRequestQueue(context),首先調(diào)用該類時(shí),重載了newRequestQueue(context,null)方法,在該方法中初始化相關(guān)信息,比如緩存地址,HttpStack。其中HttpStack為網(wǎng)絡(luò)通信的代理類,里面封裝著相應(yīng)的通信實(shí)體(在版本大于9,也就是版本大于2.3時(shí),采用的是httpClientStack,里面封裝這httpUrlConnection,小于9時(shí),采用的是httpclient),然后生成請(qǐng)求隊(duì)列實(shí)例,并start;
RequestQueue.start() 在請(qǐng)求隊(duì)列邏輯處理中,會(huì)開(kāi)啟兩種線程:緩存調(diào)度線程和網(wǎng)絡(luò)調(diào)度線程,其中緩存調(diào)度線程有1個(gè),而網(wǎng)絡(luò)調(diào)度線程默認(rèn)有4個(gè)。
-
requestQueue.add() 向請(qǐng)求隊(duì)列中加入請(qǐng)求后,就可以完成網(wǎng)絡(luò)通信了。那么add里面的操作是什么呢?
- 首先判斷該請(qǐng)求是否需要加入緩存
if (!request.shouldCache())
,如果不需要加入,則直接交給網(wǎng)絡(luò)請(qǐng)求隊(duì)列; - 需要加入緩存時(shí),會(huì)進(jìn)行判斷,看等待隊(duì)列中是否含有key,如果含有key,則將其數(shù)據(jù)加入到隊(duì)列中,放入到該隊(duì)列中。
Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);
;如果沒(méi)有相同的key,則在等待隊(duì)列中加入該key,value為null,并加入緩存線程中。接下來(lái),緩存線程就運(yùn)行起來(lái)了
- 首先判斷該請(qǐng)求是否需要加入緩存
-
緩存線程 CacheDispatcher 緩存線程的run方法中,執(zhí)行邏輯如下:
- 該線程
while(true)
,可以看出該線程一直在后臺(tái)運(yùn)行。 - 嘗試從緩存中取出緩存內(nèi)容,如果內(nèi)容為空,則直接就加入到網(wǎng)絡(luò)請(qǐng)求隊(duì)列中。緩存內(nèi)容過(guò)期,同理;
- 通過(guò)parseNetWorkResponse來(lái)對(duì)緩存內(nèi)容進(jìn)行解析,并回調(diào)。
- 該線程
-
**網(wǎng)絡(luò)通信線程 NetworkDispatcher ** 執(zhí)行邏輯如下:
- 該線程,也是一直在后臺(tái)運(yùn)行;
- 該通過(guò)performRequest()發(fā)起網(wǎng)絡(luò)請(qǐng)求。該performRequest實(shí)際上調(diào)用了BasicNetWork實(shí)現(xiàn),在其內(nèi)部,調(diào)用了httpStack的performStack,而這個(gè)就是之前實(shí)例化的httpStack。
- 通過(guò)parseNetWorkResponse來(lái)解析返回的數(shù)據(jù),并寫(xiě)入到緩存中。
- 如何回調(diào)到主線程中? 通過(guò)
ResponseDeliveryRunnable()
方法,將數(shù)據(jù)傳給response.deliverResponse();在該類中,將數(shù)據(jù)傳給response.listener的onResponse的方法中。
Volley的緩存策略###
只采用了磁盤緩存