Android WebView 缓存
现在很多门户类信息网站,比如虎嗅,ifanr,钛媒体等等的 APP,简单点说是信息阅读类的 APP,但是在文章详情页面,还是直接嵌套一个 WebView 用来显示,这可能就涉及到了 WebView 的缓存了
页面缓存
页面缓存 就是指 WebView
第一次打开某个网页时会保存加载一个网页时所需的 HTML,JS,CSS 等页面相关的数据以及其它资源,当没网的时候或者
网络状态较差的时候,加载本地保存好的相关数据
几乎所有游览器都支持页面缓存功能,因为页面缓存能加快网页浏览速度,也能节省带宽和服务器资源
本章节我们就来学习如何设置 Android WebView
的缓存功能
缓存的分类
现代浏览器中的缓存,大致可以分为两大类:页面缓存和数据缓存
-
页面缓存
加载一个网页时的 HTML、JS、CSS 等页面或者资源数据
这些缓存资源是浏览器自身的行为而产生,开发者只能通过配置 HTTP 响应头影响浏览器的行为才能间接地影响到这些缓存数据
Android Webview 页面缓存保存了两种数据
-
缓存的索引 放在
/data/data/<包名>/cache/org.chromium.android_webkit/indexdir
-
缓存的文件 放在
/data/data/<包名>/cache/org.chromium.android_webkit
-
-
数据缓存
数据缓存又两种 AppCache 和 DOM Storage
-
AppCache
AppCache
时我们能够主动选择缓存 WEB 浏览器中所有的东西,从页面、图片到脚本、CSS 等等AppCache
数据保存在 ApplicationCache.db 中AppCache 需要调用方法
setAppCacheEnabled()
手动开启,同时要设置缓存保存的路径setAppCachePath()
和容量setAppCacheMaxSize()
AppCache 目前支持
5M
的存储空间,所以使用时要谨慎,仅缓存最重要的东西 -
DOM Storage
存储一些简单的键值对(
key/value
) 数据根据作用范围的不同,分为
SessionStorage
和Local Storage
两种,分别用于会话级别的存储(页面关闭即消失)和本地化存储(除非主动删除,否则数据永远不会过期DOMStorage 数据保存在
/data/data/<包名>/app_webview/Local Storage/<filename>.localstorage
Android 需要调用方法
setDomStorageEnabled()
手动开启 DOM Storage 并调用方法setDatabasePath()
设置存储路径
-
WebView 缓存模式
模式 | 说明 |
---|---|
LOAD_CACHE_ONLY | 不使用网络,只读取本地缓存数据 |
LOAD_DEFAULT | 根据cache-control决定是否从网络上取数据。 |
LOAD_CACHE_NORMAL已废弃 | 作用同 LOAD_DEFAULT 模式 |
LOAD_NO_CACHE | 不使用缓存,只从网络获取数据 |
LOAD_CACHE_ELSE_NETWORK | 只要本地有,无论是否过期,或者 no-cache,都使用缓存中的数据 |
开发中,我们建议缓存策略为
判断是否有网络,有的话,使用 LOAD_DEFAULT 无网络,使用 LOAD_CACHE_ELSE_NETWORK
删除 WebView 的缓存数据
如果要删除 WebView 的缓存数据,可以调用 clearCache( true )
方法
当然了,WebView
还提供了大量的其它方法用于删除各种缓存
方法 | 说明 |
---|---|
setting.setCacheMode(WebSettings.LOAD_NO_CACHE) | 设置 WebView 不缓存,不缓存也就没缓存数据要删除了 |
deleteDatabase("WebView.db") deleteDatabase("WebViewCache.db") |
删除缓存的数据库 |
webView.clearHistory() | 删除历史访问记录 |
webView.clearFormData() | 删除自动表单数据 |
getCacheDir().delete() | 删除缓存目录 |
WebView 开启缓存功能
操作过程如下
- 进入页面后默认加载 url,然后随便点击一个链接跳到第二个页面,退出 APP
- 开启飞行模式,关闭 wifi 以及移动网络,然后重新进入,发现无网络的情况下,页面还是加载了,打开第一个链接也可以加载,打开其它链接就发现找不到网页
- 点击清除缓存,把应用关闭,重新进入,发现页面已经打不开
-
创建一个 空的 Android 项目
cn.twle.android.WebViewCache
-
修改
AndroidManifest.xml
添加网络权限<uses-permission android:name="android.permission.INTERNET" />
-
修改
activity_main.xml
添加一个WebView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:padding="5dp" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_refresh" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="刷新" /> <Button android:id="@+id/btn_clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/btn_refresh" android:text="清除缓存" /> <WebView android:id="@+id/ms_webview" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
-
修改
MainActivity.java
package cn.twle.android.webviewcache; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import java.io.File; public class MainActivity extends AppCompatActivity { private WebView ms_webview; private Button btn_clear_cache; private Button btn_refresh; private static final String APP_CACHE_DIRNAME = "/webcache"; // web 缓存目录 private static final String SITE_URL = "https://www.twle.cn/static/i/android/demo_a.html"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ms_webview = (WebView) findViewById(R.id.ms_webview); btn_refresh = (Button) findViewById(R.id.btn_refresh); btn_clear_cache = (Button) findViewById(R.id.btn_clear); ms_webview.loadUrl(SITE_URL); ms_webview.setWebViewClient(new WebViewClient() { //设置在 WebView 点击打开的新网页在当前界面显示,而不跳转到新的浏览器中 @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } }); WebSettings settings = ms_webview.getSettings(); settings.setJavaScriptEnabled(true); //设置缓存模式 settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); // 开启DOM storage API 功能 settings.setDomStorageEnabled(true); // 开启database storage API功能 settings.setDatabaseEnabled(true); String cacheDirPath = getCacheDir().getAbsolutePath() + APP_CACHE_DIRNAME; Log.d("webcache",cacheDirPath); File f = new File(cacheDirPath); if (!f.exists()) { f.mkdirs(); } // 设置数据库缓存路径 settings.setAppCachePath(cacheDirPath); settings.setAppCacheEnabled(true); btn_clear_cache.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ms_webview.clearCache(true); } }); btn_refresh.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ms_webview.reload(); } }); } // 重写回退按钮的点击事件 @Override public void onBackPressed() { if (ms_webview.canGoBack()) ms_webview.goBack(); else super.onBackPressed(); } }