webview自定義緩存方案

需求背景:使用webview加載大圖的時候自定義緩存,把網頁中約定的大圖片緩存到本地,第二次打開同一張頁面的時候直接從本地緩存中讀取
在使用webview的時候,對於一些資源的加載,特別是一些大圖的加載是比較耗時的操作。雖然webview自帶了一些混存機制,但是這篇文章主要討論下如何自定義緩存來保存網頁中的大圖片資源。

實現功能:第一次從網絡上加載,加載成功後存到本地後,接下來都是通過匹配url從緩存裏,並且這些都不是用webview自帶的緩存。
獲取緩存的實現代碼如下(Kotlin代碼)

fun getURLcached(url: String): String {
        //val imgPath ="/mnt/internal_sd/cjcool/mallservice/pic/a8bb5fab7436f478d5541c7ba1a18ecd.png"
        val mdevalue = MD5Util.md5(url)
        // MD5Util進行md5加密
        val filename = mdevalue + ".png"
        val folderpath = FolderUtil.getMallServicePicDir()
        val target = File(folderpath + File.separator + filename)
        val mallServiceQrPath = target.absolutePath
        if (!target.exists()) {
            HttpDownloader.INSTANCE().downloadByDownloader(url, mallServiceQrPath, object : IoListener {
                override fun onComplete(uri: String, local: String) {
                    LogUtil.d("downloadByDownloader success")
                }
                override fun onFail(uri: String, local: String, tag: Any) {
                    LogUtil.d("downloadByDownloader onfailed")
                }
            })
            return url
        } else {
            //Log.d("TAG", "prqel getURLcached" + target.absolutePath);
            return target.absolutePath
        }
    }

這段代碼對url進行md5加密,然後通過對比,從指定文件路徑查找緩存。
那麼如何讓webview攔截到加載的resource呢?
我們知道WebViewClient 提供了onPageStarted,onLoadingResource等方法,這裏用到的是webview的shouldInterceptRequest方法,該方法是在webview加載圖片資源的時候會回調。
既然shouldInterceptRequest方法攔截到webview加載的資源,這樣的話客戶端在開發之前先和服務端開發人員約定一個關鍵字,對於有關鍵字的u rl資源進行本地緩存,沒有關鍵字的url資源不進行本地緩存。

 override fun shouldInterceptRequest(webView: WebView?, webResourceRequest: WebResourceRequest?): WebResourceResponse? {
            val input: FileInputStream
            val url = webResourceRequest?.getUrl()

            /*如果請求包含約定的字段 說明是要拿本地的圖片*/
            if (url.toString().contains(cachekey)) {
                val curl =  url.toString().replace("?androidimg","")
                val imgPath = getURLcached(curl)
                LogUtil.i("本地圖片路徑:" + imgPath.trim({ it <= ' ' }))
                try {
                    /*重新構造WebResourceResponse  將數據已流的方式傳入*/
                    input = FileInputStream(File(imgPath.trim({ it <= ' ' })))
                    val response = WebResourceResponse("image/jpg", "UTF-8", input)
                    /*返回WebResourceResponse*/
                    return response
                } catch (e: FileNotFoundException) {
                    e.printStackTrace()
                }
            }
            //webview.loadUrl(url)
            return super.shouldInterceptRequest(webView, webResourceRequest)
        }
    }

** 圖片的路徑通過WebResourceRequest.getUrl().getpath來獲取,後面的getpath不能漏掉,否則攔截過的url地址會不正確**。

另外值得注意的是,這種自定義緩存的方式需要將webview的setAllowFileAccess屬性設置爲true,即關閉webview本身的其他自帶緩存機制,分別需要執行 webSetting.setAppCacheEnabled(false)還有webSetting.setCacheMode這兩句代碼,這兩者對應緩存的對象可以去網上查找一下,然後前者設置爲false,後者setCacheMode設置爲WebSettings.LOAD_NO_CACHE。
這樣才保證在shouldInterceptRequest攔截到所有的加載資源。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章