瀏覽器緩存,相信前端同窗對這幾個字眼很是熟悉,那麼今天從新來解讀一下這個概念,並根據其原理擴展到native中如何使用。html
第一部分,先來談談瀏覽器緩存原理,這樣的文章網上都已經很了,但爲了第二部分敘述,此處仍是囉嗦一下。可參考瀏覽器緩存機制。前端
這裏主要介紹跟HTTP相關的緩存,主要依賴Expires/Cache-Control和304返回碼實現的緩存邏輯。git
HTTP1.0中請求頭中存在Expires字段,顧名思義,用來設置網絡資源的過時時間;github
HTTP1.1對緩存頭信息進行了豐富,包括Cache-Control,以及跟Cache-Control相關的Last-Modified/If-Modified-Since和Etag/If-None-Match,web
其中Cache-Control中的max-age能夠設置資源的緩存時間,而Last-Modified是服務器告訴瀏覽器資源的最後修改時間,Etag是服務器告訴瀏覽器資源的Hash值,數據庫
用來表明資源的 惟一值(好比百度雲盤秒傳機制,即檢測文件Hash值後在網絡庫中進行匹配,省去無效的上傳時間)。瀏覽器
當瀏覽器第一次訪問服務器資源後,會對服務器返回的頭信息進行存儲,方便之後請求時判斷緩存是否有效。緩存
配合這些字段瀏覽器便可實現對資源的緩存控制,主要流程以下:服務器
1.若是請求不支持Cache-Control,則使用Expires來判斷資源是否過時;網絡
2.若是請求支持Cache-Control,則先判斷(第一次請求時間)+max-age>(當先請求時間),若是成立則直接讀取本地緩存(也就是Chrome DevTool中看到的from cache);
3.若是不成立,則判斷資源是否存在Etag,若是存在該字段,則在請求中加上If-None-Match頭並帶入Etag值,等待服務器判斷該Etag是否無效,若是有效則返回304,直接讀取本地緩存,若是Etag無效則返回200並返回新的資源;
4.若是不存在Etag資源,則判斷是否存在Last-Modified,若是存在則在請求中加上If-Modified-Since頭並帶入Last-Modified值,等待服務器判斷資源是否過時,若是未過時則返回304,直接讀取本地緩存,若是過時則返回200並返回新的資源;
5.若是這Etag和Last-Modified兩個信息都不存在,則直接向服務器發起新的請求,服務器返回200並返回新的資源,並將其緩存到瀏覽器本地。
至此,瀏覽器請求時緩存機制已所有完成,其流程以下圖描述。
第二部分,聊完了瀏覽器的緩存機制,那麼在其餘客戶端場景是否能運用該機制,起到緩存網絡資源做用。這裏主要介紹Android客戶端模擬瀏覽器緩存請求網絡圖片。
在移動客戶端Android中請求網絡資源時,咱們能夠利用HTTP自帶緩存頭特性來緩存圖片。那麼如何來獲取及保存Cache-Control/Last-Modified/Etag等緩存相關參數,
則須要在本地文件系統中創建相應數據庫及表用來存儲這些信息。大體以下表。
ID | PROTO | HOST | PORT | PATH | PARAMS | First-Request-Time | CACHE-CONTROL | LAST-MODIFIED | ETAG |
1 | http | secure.*.com | 80 | /webapp/index | token=xxx | 2015-09-10 11:16:43 | max-age:30000 | Thu, 17 Sep 2015 11:16:43 GMT | 8dYKoCv***Rn6XX0= |
前面的PROTO/HOST/PORT/PATH/PARAMS主要用來構建HTTP URL,後4個則用來資源緩存相關的信息,主要流程與瀏覽器請求網絡資源基本一致。
先判斷Cache-Control是否過時,若是過時則檢查ETAG,若是ETAG沒有則檢查LAST-MODIFIED,若是LAST-MODIFIED也沒有則直接請求,將請求對應的返回頭信息寫入數據庫便可。
上面基本描述了模擬瀏覽器緩存構造Android客戶端緩存的原理,其細節則再也不描述,可參考開源庫GALHTTPREQUEST。