当我们加载Html时候,会在我们data/应用package下生成database与cache两个文件夹:

我们请求的Url记录是保存在webviewCache.db里,而url的内容是保存在webviewCache文件夹下.

WebView中存在着两种缓存:网页数据缓存(存储打开过的页面及资源)、H5缓存(即AppCache)。

一、网页缓存

1、缓存构成

/data/data/package_name/cache/

/data/data/package_name/database/webview.db

/data/data/package_name/database/webviewCache.db

综合可以得知 webview 会将我们浏览过的网页url已经网页文件(css、图片、js等)保存到数据库表中

缓存模式(5种)

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,都使用缓存中的数据。

如:www.taobao.com的cache-control为no-cache,在模式LOAD_DEFAULT下,无论如何都会从网络上取数据,如果没有网络,就会出现错误页面;在LOAD_CACHE_ELSE_NETWORK模式下,无论是否有网络,只要本地有缓存,都使用缓存。本地没有缓存时才从网络上获取。

www.360.com.cn的cache-control为max-age=60,在两种模式下都使用本地缓存数据。





总结:根据以上两种模式,建议缓存策略为,判断是否有网络,有的话,使用LOAD_DEFAULT,无网络时,使用LOAD_CACHE_ELSE_NETWORK。

设置WebView 缓存模式

    private void initWebView() {  

            mWebView.getSettings().setJavaScriptEnabled(true);
            mWebView.getSettings().setRenderPriority(RenderPriority.HIGH);
            mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);  //设置 缓存模式
            // 开启 DOM storage API 功能
            mWebView.getSettings().setDomStorageEnabled(true);
            //开启 database storage API 功能
            mWebView.getSettings().setDatabaseEnabled(true);
            String cacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME;
    //      String cacheDirPath = getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME;
            Log.i(TAG, "cacheDirPath="+cacheDirPath);
            //设置数据库缓存路径
            mWebView.getSettings().setDatabasePath(cacheDirPath);
            //设置  Application Caches 缓存目录
            mWebView.getSettings().setAppCachePath(cacheDirPath);
            //开启 Application Caches 功能
            mWebView.getSettings().setAppCacheEnabled(true);
        }  

清除缓存

    /**
         * 清除WebView缓存
         */
        public void clearWebViewCache(){  

            //清理Webview缓存数据库
            try {
                deleteDatabase("webview.db");
                deleteDatabase("webviewCache.db");
            } catch (Exception e) {
                e.printStackTrace();
            }  

            //WebView 缓存文件
            File appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME);
            Log.e(TAG, "appCacheDir path="+appCacheDir.getAbsolutePath());  

            File webviewCacheDir = new File(getCacheDir().getAbsolutePath()+"/webviewCache");
            Log.e(TAG, "webviewCacheDir path="+webviewCacheDir.getAbsolutePath());  

            //删除webview 缓存目录
            if(webviewCacheDir.exists()){
                deleteFile(webviewCacheDir);
            }
            //删除webview 缓存 缓存目录
            if(appCacheDir.exists()){
                deleteFile(appCacheDir);
            }
        }  

完整代码

package com.example.webviewtest;  

import java.io.File;  

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.RenderPriority;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;  

public class MainActivity extends Activity {  

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final String APP_CACAHE_DIRNAME = "/webcache";
    private TextView tv_topbar_title;
    private RelativeLayout rl_loading;
    private WebView mWebView;
    private String url;  

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);  

        //url:http://m.dianhua.cn/detail/31ccb426119d3c9eaa794df686c58636121d38bc?apikey=jFaWGVHdFVhekZYWTBWV1ZHSkZOVlJWY&app=com.yulore.yellowsdk_ios&uid=355136051337627
        url = "http://m.dianhua.cn/detail/31ccb426119d3c9eaa794df686c58636121d38bc?apikey=jFaWGVHdFVhekZYWTBWV1ZHSkZOVlJWY&app=com.yulore.yellowsdk_ios&uid=355136051337627";
        findView();
    }  

    private void findView() {  

        tv_topbar_title = (TextView) findViewById(R.id.tv_topbar_title);  

        rl_loading = (RelativeLayout) findViewById(R.id.rl_loading);  

        mWebView = (WebView) findViewById(R.id.mWebView);  

        initWebView();  

        mWebView.setWebViewClient(new WebViewClient() {  

            @Override
            public void onLoadResource(WebView view, String url) {  

                Log.i(TAG, "onLoadResource url="+url);  

                super.onLoadResource(view, url);
            }  

            @Override
            public boolean shouldOverrideUrlLoading(WebView webview, String url) {  

                Log.i(TAG, "intercept url="+url);  

                webview.loadUrl(url);  

                return true;
            }  

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {  

                Log.e(TAG, "onPageStarted");  

                rl_loading.setVisibility(View.VISIBLE); // 显示加载界面
            }  

            @Override
            public void onPageFinished(WebView view, String url) {  

                String title = view.getTitle();  

                Log.e(TAG, "onPageFinished WebView title=" + title);  

                tv_topbar_title.setText(title);
                tv_topbar_title.setVisibility(View.VISIBLE);  

                rl_loading.setVisibility(View.GONE); // 隐藏加载界面
            }  

            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {  

                rl_loading.setVisibility(View.GONE); // 隐藏加载界面  

                Toast.makeText(getApplicationContext(), "",
                        Toast.LENGTH_LONG).show();
            }
        });  

        mWebView.setWebChromeClient(new WebChromeClient() {  

            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {  

                Log.e(TAG, "onJsAlert " + message);  

                Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();  

                result.confirm();  

                return true;
            }  

            @Override
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {  

                Log.e(TAG, "onJsConfirm " + message);  

                return super.onJsConfirm(view, url, message, result);
            }  

            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {  

                Log.e(TAG, "onJsPrompt " + url);  

                return super.onJsPrompt(view, url, message, defaultValue, result);
            }
        });  

        mWebView.loadUrl(url);
    }  

    private void initWebView() {  

        mWebView.getSettings().setJavaScriptEnabled(true);
        mWebView.getSettings().setRenderPriority(RenderPriority.HIGH);
        mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);  //设置 缓存模式
        // 开启 DOM storage API 功能
        mWebView.getSettings().setDomStorageEnabled(true);
        //开启 database storage API 功能
        mWebView.getSettings().setDatabaseEnabled(true);
        String cacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME;
//      String cacheDirPath = getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME;
        Log.i(TAG, "cacheDirPath="+cacheDirPath);
        //设置数据库缓存路径
        mWebView.getSettings().setDatabasePath(cacheDirPath);
        //设置  Application Caches 缓存目录
        mWebView.getSettings().setAppCachePath(cacheDirPath);
        //开启 Application Caches 功能
        mWebView.getSettings().setAppCacheEnabled(true);
    }  

    /**
     * 清除WebView缓存
     */
    public void clearWebViewCache(){  

        //清理Webview缓存数据库
        try {
            deleteDatabase("webview.db");
            deleteDatabase("webviewCache.db");
        } catch (Exception e) {
            e.printStackTrace();
        }  

        //WebView 缓存文件
        File appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME);
        Log.e(TAG, "appCacheDir path="+appCacheDir.getAbsolutePath());  

        File webviewCacheDir = new File(getCacheDir().getAbsolutePath()+"/webviewCache");
        Log.e(TAG, "webviewCacheDir path="+webviewCacheDir.getAbsolutePath());  

        //删除webview 缓存目录
        if(webviewCacheDir.exists()){
            deleteFile(webviewCacheDir);
        }
        //删除webview 缓存 缓存目录
        if(appCacheDir.exists()){
            deleteFile(appCacheDir);
        }
    }  

    /**
     * 递归删除 文件/文件夹
     *
     * @param file
     */
    public void deleteFile(File file) {  

        Log.i(TAG, "delete file path=" + file.getAbsolutePath());  

        if (file.exists()) {
            if (file.isFile()) {
                file.delete();
            } else if (file.isDirectory()) {
                File files[] = file.listFiles();
                for (int i = 0; i < files.length; i++) {
                    deleteFile(files[i]);
                }
            }
            file.delete();
        } else {
            Log.e(TAG, "delete file no exists " + file.getAbsolutePath());
        }
    }  

}  

Android WebView 缓存机制和模式详解的更多相关文章

  1. PHP缓存机制Output Control详解

    开启OB缓存的方式有如下两种: 1. php.ini中开启 output_buffering = 4096 启用了此指令,那么每个PHP脚本都相当于一开始就调用了ob_start()函数,PHP5.5 ...

  2. H5 和移动端 WebView 缓存机制解析与实战

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/qHm_dJBhVbv0pJs8Crp77w 作者:叶 ...

  3. HTTP协议头部与Keep-Alive模式详解

    HTTP协议头部与Keep-Alive模式详解 .什么是Keep-Alive模式? 我们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器 ...

  4. HTTP协议Keep-Alive模式详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp22 HTTP协议Keep-Alive模式详解 1.什么是Keep-Aliv ...

  5. Android 广播大全 Intent Action 事件详解

    Android 广播大全 Intent Action 事件详解 投稿:mrr 字体:[增加 减小] 类型:转载 时间:2015-10-20我要评论 这篇文章主要给大家介绍Android 广播大全 In ...

  6. 大数据学习笔记——Spark工作机制以及API详解

    Spark工作机制以及API详解 本篇文章将会承接上篇关于如何部署Spark分布式集群的博客,会先对RDD编程中常见的API进行一个整理,接着再结合源代码以及注释详细地解读spark的作业提交流程,调 ...

  7. Android EventBus 3.0 实例使用详解

    EventBus的使用和原理在网上有很多的博客了,其中泓洋大哥和启舰写的非常非常棒,我也是跟着他们的博客学会的EventBus,因为是第一次接触并使用EventBus,所以我写的更多是如何使用,源码解 ...

  8. Android开发:文本控件详解——TextView(一)基本属性

    一.简单实例: 新建的Android项目初始自带的Hello World!其实就是一个TextView. 在activity_main.xml中可以新建TextView,从左侧组件里拖拽到右侧预览界面 ...

  9. Apache 工作模式详解

    Apache 工作模式详解 Apache 2.X  支持插入式并行处理模块,称为多路处理模块(MPM).在编译apache时必须选择也只能选择一个MPM,对类UNIX系统,有几个不同的MPM可供选择, ...

随机推荐

  1. Technical debt

    What is Technial debt? Technical debt is not bug. It is that the feature can work, but it is not a p ...

  2. python函数式编程之装饰器(一)

    1.开放封闭原则 简单来说,就是对扩展开放,对修改封闭 在面向对象的编程方式中,经常会定义各种函数. 一个函数的使用分为定义阶段和使用阶段,一个函数定义完成以后,可能会在很多位置被调用 这意味着如果函 ...

  3. xBIM IFC 输出 Excel 报表

    目录 xBIM 应用与学习 (一) xBIM 应用与学习 (二) xBIM 基本的模型操作 xBIM 日志操作 XBIM 3D 墙壁案例 xBIM 格式之间转换 xBIM 使用Linq 来优化查询 x ...

  4. Java中的递归调用

    Java中不合理的使用递归调用,可能会导致栈内存溢出,这点是需要注意的. java将为每个线程维护一个栈,栈里将为每个方法保存一个栈帧,栈帧代表了一个方法的运行状态. 也就是我们常说的方法栈.最后一个 ...

  5. Python基础篇(二)

    Python最基本的数据结构是序列(sequence),序列中的每个元素被分以以0开头的唯一的一个id号. Python中有6种内建的序列:列表,元组,字符串,Unicode字符串,buffer对象和 ...

  6. 使用exe4j工具制作简单的java应用程序

    首先需要下载exe4j工具并进行安装,下面是利用exe4j工具制作应用程序的步骤. 1.首先将工程导出为可运行的jar包,选择extract required libralies into gener ...

  7. win2012 配置wamp的若干错误

    转自群友 VC2015.VC14 在 Windows 2012 R2 安装失败,0x80240017 - 未指定的错误,解决办法据朋友反应VC2013一样存在这个问题--查资料说是没有安装 KB299 ...

  8. 计算机基础之Windows10操作系统安装U盘制作

    1.第一步,下载Windows10--ISO镜像(Windows7类似),下载站点: https://msdn.itellyou.cn/(百度搜索msdn即可),个人认为这是最干净的操作系统镜像站点, ...

  9. vscode php跳转

    最近在写一个php项目,最后选定使用vscode编辑器,然后研究了一下断点调试.格式代码.点击跳转 以下是配置步骤,记录一下 1.代码格式化及跳转  1.前提条件:安装7.0以上版本php,     ...

  10. [翻译]编写高性能 .NET 代码 第二章:垃圾回收

    返回目录 第二章:垃圾回收 垃圾回收是你开发工作中要了解的最重要的事情.它是造成性能问题里最显著的原因,但只要你保持持续的关注(代码审查,监控数据)就可以很快修复这些问题.我这里说的"显著的 ...