需求背景:使用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(WebSettings.LOAD_NO_CACHE)
这两句代码,
两者对应缓存的对象可以去网上查找一下,然后前者设置为false,后者setCacheMode设置为WebSettings.LOAD_NO_CACHE。
这样才保证在shouldInterceptRequest拦截到所有的加载资源。