继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

WebView自定义缓存路径

jeck猫
关注TA
已关注
手记 416
粉丝 74
获赞 402

首先推荐一个讲解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

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP