WebView自定義快取路徑

jerrysun發表於2021-09-09

首先推薦一個講解WebViewClient自帶控制快取的部落格:http://blog.csdn.net/a345017062/article/details/8573689

WebViewClient自帶快取設定是這樣的:LOAD_CACHE_ONLY只載入快取; LOAD_CACHE_ELSE_NETWORK 無論是否過期,都載入快取。本地沒有快取時再從網路載入;LOAD_DEFAULT根據web端控制;LOAD_NO_CACHE不用快取;

那麼WebView快取的設定,通常我們會選擇這樣做:如果有網LOAD_DEFAULT;反之 LOAD_CACHE_ELSE_NETWORK;言外之意要麼根據Web端去控制,要麼就只載入快取,網路沒機會載入。是不是感覺快取機制不是很完美?

如果我們想完善一下,這樣:有快取就先載入快取,再載入網路,替換快取檔案,無快取直接載入網路,無網異常機制。當然這只是一種方案,其他更好的方案歡迎交流。

想這樣,再打算依賴Api自帶快取設定就有點捉襟見肘了,那麼我們自己來實現吧

WebViewClient 自帶了一個攔截請求的方法:shouldInterceptRequest,返回攔截到的資源。但是存在api版本限制,低版本無法透過該方法實現請求攔截。

我們是否可以參考這個攔截思路,發起請求獲取網頁內容並將其轉換成我們的本地儲存,再去用WebView載入這個本地儲存呢?

答案是肯定的!

WebView的load方法有多種,通常我們沒有特殊需求會用WebView.loadUrl(String)。另外還有載入本地頁面、本地資源的方法,請看:

[程式碼]java程式碼:


loadData(String html,String mimeType,String encoding)

[程式碼]java程式碼:


loadDataWithBaseURL(String baseUrl, String data,String mimeType, String encoding, String historyUrl);


第一個方法需要的是整個Html頁面,我們頁面簡單的話,可以全部down下來然後作為本地快取頁面載入;but!誰敢保證我們日常頁面很簡單?既然選擇最佳化,那就把活幹的全面一點吧,我們來看第二個方法:url、資料、型別、編碼、history;這裡不考慮頁面前進後退等問題,那是另一種實現。詳細Api就不細說了。根據這個方法我們反推一下載入快取頁面的實現思路:

String 型別的Data使我們要載入的內容,內容來源於網頁,網頁是不是可以透過網路請求獲取?再提供頁面一些關鍵引數,最終完成快取載入路線,齊活!

快取思路:開啟子執行緒>使用Http協議>獲取網頁資源>儲存到指定路徑>構造String型別>使用load方法載入快取

下面看網路請求獲取網頁,這裡我們使用HttpURLConnection,已知url:

[程式碼]java程式碼:


InputStream inputStream = null;    HttpURLConnection httpConnection = null;    try {        URL url = new URL(url);         if (url == null) {                      return null;        }        httpConnection = (HttpURLConnection) url .openConnection();        if (httpConnection == null) {            return null;        }        httpConnection.setConnectTimeout(500);        httpConnection.setReadTimeout(500);         int responseCode = httpConnection.getResponseCode();               if (responseCode == HttpURLConnection.HTTP_OK) {            inputStream = httpConnection.getInputStream();        }        if (inputStream == null)            return null;        byte[] inputDatas = readBytes(inputStream); //將輸入流轉換成位元組陣列儲存,這裡不再敘述        return inputDatas ;     } catch (Exception e) {        e.printStackTrace();        return null;    } finally {        if (inputStream != null)//關閉資源            try {                inputStream.close();            } catch (IOException e1) {                e1.printStackTrace();            }        if (httpConnection != null) {            httpConnection.disconnect();        }       //將我們獲取的資源進行本地序列化,這裡不貼出實現方案    }

至此,我們有了網頁內容,剩下的minyType以及encoding最好還是從Http請求頭中獲取,HttpURLConnection.getContentType(),解析方案各種斟酌,見仁見智。

好了,快取有了,我們調上面那個load方法試試看:loadDataWithBaseURL(url, new String(byte[]data), mimeType,  encoding, null);

哦了。

剩下的就是策略問題了:快取載入完了,再載入網路還遠麼?為了避免WebView自帶的快取策略影響我們快取的更新,我們不使用loadUrl,還用上面那個HttpUrlConnection去載入頁面,來完成我們快取的更新動作,此時新的快取就是我們載入完網路頁面之後的新內容,可以將其作為網路內容看待。


而整體控制快取與網路的實現可以是這樣的:

無網,載入快取,無快取,失敗;

有網,載入快取,同時獲取網路頁面更新快取,載入新快取更新頁面顯示,舊快取沒有,新快取也沒有,失敗。

這麼做的好處是什麼?打個比方,WebView頁面通常屬於強展示弱互動頁面,而這些頁面的展示優先程度就會比較高,頁面內容的變化也會比較頻繁。通常按預設的處理會是這樣:載入網路頁面,而網路又經常特別慢,頁面就會經常等待很久,而我們有快取了,但是過期了,那就等吧。

我們按上面的方案處理了之後,可以變成這樣:不考慮快取有效期,快速展示本地快取頁面,這個過程中無論網路如何,新快取是否更新完成,我們可愛的使用者都已經看到了頁面,當網路載入完成,頁面重新整理。完美


原文連結:http://www.apkbus.com/blog-35555-68640.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/151/viewspace-2813740/,如需轉載,請註明出處,否則將追究法律責任。

相關文章