webview加载html的离线缓存

来源:互联网 发布:口碑和淘宝外卖一样么 编辑:程序博客网 时间:2024/05/29 17:31

首先知道webview自带离线缓存功能:

        mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);  //设置 缓存模式

LOAD_CACHE_ONLY:  不使用网络,只读取本地缓存数据
LOAD_DEFAULT:  根据cache-control决定是否从网络上取数据。
LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

// 开启 DOM storage API 功能 
        mWebView.getSettings().setDomStorageEnabled(true); 
        //开启 database storage API 功能 
        mWebView.getSettings().setDatabaseEnabled(true);  
        String cacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME; 
        //设置数据库缓存路径 
        mWebView.getSettings().setDatabasePath(cacheDirPath); 
        //设置  Application Caches 缓存目录 
        mWebView.getSettings().setAppCachePath(cacheDirPath); 
        //开启 Application Caches 功能 
        mWebView.getSettings().setAppCacheEnabled(true); 
但是这都是通过直接加载一个URL来缓存的,而我的要求是加载本地的html,在html中有图片需要网络加载,html可以通过加网络请求后缓存到本地,但是其中的图片加载需要下载才能实现缓存的要求:

具体思路是通过得到HTML中的图片地址,然后下载,然后对webview更新,网上找到的资料是用js代码更新,但是测试的时候没有效果,所以我的思路是:

1.第一次加载时直接加载原html数据,其中的图片从网络加载;

2.将html代码中img标签替换为本地地址,并且将html代码缓存到本地,并且开始下载图片

3.再次读取该网页时首先判断本地是否有该网页的html代码,有的话读取本地已经替换过img标签的html代码;

4.由于图片已经下载在本地,加载该html代码时图片就从本地加载的,从而达到缓存的效果;

代码:

第一步:第一次加载时直接加载原html数据,其中的图片从网络加载,并且开始下载图片;

这是存储及读取html代码的部分,key为文件名,用URL,但是有//符号,最好用MD5进行编码,否则会报错

public static void saveHtml(String key, String value, Context ctx) {    key = MD5Utils.encode(key);    FileOutputStream fileOutputStream = null;    BufferedWriter writer = null;    try {        fileOutputStream = ctx.openFileOutput(key, Context.MODE_APPEND);        writer = new BufferedWriter(new OutputStreamWriter(fileOutputStream));        writer.write(value);    } catch (FileNotFoundException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    } finally {        if (writer != null) {            try {                writer.flush();                writer.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}public static String getHtml(String key, Context ctx) {    key = MD5Utils.encode(key);    FileInputStream fileInputStream = null;    BufferedReader reader = null;    StringBuilder builder = null;    try {        fileInputStream = ctx.openFileInput(key);        reader = new BufferedReader(new InputStreamReader(fileInputStream));        builder = new StringBuilder();        String line = "";        while ((line = reader.readLine()) != null) {            builder.append(line);        }    } catch (FileNotFoundException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    } finally {        if (reader != null) {            try {                reader.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }    if (builder != null) {        return builder.toString();    }    return null;}

然后加载时先读取本地,如果没有该文件就读取网络数据:

final String url = GlobalContants.TEXT_URL;responseHtml = CacheUtils.getHtml(url, getActivity());httpUtils = new HttpUtils();if (TextUtils.isEmpty(responseHtml)) {    httpHandler = httpUtils.send(HttpRequest.HttpMethod.GET, url,            new RequestCallBack<String>() {                @Override                public void onSuccess(ResponseInfo<String> responseInfo) {                    responseHtml = responseInfo.result;                }                @Override                public void onFailure(HttpException error, String msg) {                }            });}
然后webview.loadDataWtihBaseURL对这段html加载就可以了。

第二步:将html代码中img标签替换为本地地址,并且将html代码缓存到本地,并且开始下载图片

将从网络加载的html代码的img标签进行替换,然后保存到本地:

public void changeHtml(String htmlString) {    imgUrls.clear();    doc = Jsoup.parse(htmlString);//将html字符串解析为Document    if (doc == null) {        return;    }    Elements es1 = doc.select("script");    if (es1 != null) {        es1.remove();    }    Elements es = doc.getElementsByTag("img");    for (Element e : es) {        String imgUrl = e.attr("src");        imgUrls.add(imgUrl);//将图片的网络地址保存到list        String imgName;        int index = imgUrl.lastIndexOf("/");        imgName = imgUrl.substring(index + 1, imgUrl.length());//通过URL截取到图片名       String filePath = "file:///" + Environment.getExternalStorageDirectory() + "/test/" + imgName;        e.attr("src", filePath);//替换img标签的src属性内容            }    CacheUtils.saveHtml(key, doc.html(), context);//将替换img标签的html保存到本地    downloadImg(imgUrls);//开始下载图片到本地}
这里需要使用jsoup这个包,将html解析为Document,然后遍历img标签,将其中的URL保存到list中,然后替换为本地地址,注意地址前需要加
"file:///"

这样就可以在html代码中加载本地图片,在这里需要将这段更改后的html代码保存到本地,并开始下载:

这里我使用的是Xutils来进行下载,注意下载路径是上面标签替换的路径:

private void downloadImg(final List<String> imgUrls) {    //若传入参数为空,则直接返回    if (imgUrls.size() == 0)        return;    File dir = new File(Environment.getExternalStorageState() + "/anytime/");    if (!dir.exists()) {        dir.mkdir();    }    for (final String urlStr : imgUrls) {        if (urlStr == null) {            continue;        }        int index = urlStr.lastIndexOf("/");        String fileName = urlStr.substring(index + 1, urlStr.length());        File file = new File(Environment.getExternalStorageDirectory() + "/anytime/" + fileName);        if (file.exists()) {            continue;        }        try {            file.createNewFile();        } catch (IOException e) {            e.printStackTrace();        }        HttpUtils http = new HttpUtils();            /*1.下在文件的地址。2.保存至本地的文件路径。*/        HttpHandler handler = http.download(urlStr, file.getPath(), false, false,                new RequestCallBack<File>() {                    @Override                    public void onStart() {                    }                    @Override                    public void onLoading(long total, long current,                                                            boolean isUploading) {                    }                    @Override                    public void onSuccess(ResponseInfo<File> responseInfo) {                    }                    @Override                    public void onFailure(HttpException error, String msg) {                    }                });    }}
需要将上面报错图片网络地址的list传入就可以,注意http.download的参数,第四个必须为false,如果为true的话可能会将图片的名字更改,我在做的过程中就遇到了这个问题。

第三步,第四部:再次读取时所有资源都来自本地


测试过程中还可以,但是想到一种情况,就是图片没有下载完毕,但是下次读取时因为是本地的html代码,其中的img标签已经被替换,所以本地没有,网络地址也没有,就会读取图片失败,所以我的思路就是讲图片网络地址保存在img标签的属性下,读取本地html时检验一下是否所有img标签下的图片都下载了,如果没有下载就将该标签下的src属性替换回网络地址,这样webview加载时本地有的图片就加载本地,本地没有则加载网络图片。





0 0
原创粉丝点击