Android WebView 响应缓存
在 Android开发中,经常用到 WebView 进行 Hybrid 模式开发,而 缓存是 常见的优化方式。
一、WebView 缓存模式
Android WebView 通过 WebSettings.setCacheMode
设置缓存方式。
有 5 种模式,实际现在 4 种:
缓存方式 | 说明 |
---|---|
LOAD_DEFAULT | 默认处理方式,缺省 启发式缓存 |
LOAD_NO_CACHE | 不走缓存,直接从网络获取 |
LOAD_CACHE_ONLY | 不使用网络,仅从缓存加载 |
LOAD_CACHE_ELSE_NETWORK | 先取缓存(即使已过期),不存在则再网络获取 |
同LOAD_DEFAULT,api17 已摒弃 |
二、HTTP缓存
2.1 服务端,响应缓存控制
1. Cache-Control,max-age指定 缓存有效期(单位秒)
// 缓存有效期 1 小时
Cache-Control: max-age=3600
2. Expires,指定 具体过期时间
Expires: Tue, 28 Feb 2022 22:22:22 GMT
注:当
Expires
和Cache-Control
同时存在时,优先使用 Cache-Control。Expires
存在 时间格式复杂 和 系统时钟修改导致问题,推荐使用Cache-Control
。
2.2 缓存状态
HTTP响应缓存状态:fresh 和 stale。
以响应 Cache-Control: max-age=3600
为例:
- 1小时内 再请求,状态为 fresh,取缓存;
- 超出一小时 再请求,状态为 stale,进行 网络请求。
当状态为 stale 时,网络请求 重新获取。但可能存在 验证缓存 逻辑,网络返回 304
状态码,继续使用缓存。
2.3 验证缓存
常见的2种方式:
- 服务端响应
Last-Modified
+ 浏览器请求If-Modified-Since
- 服务端响应
ETag
+ 浏览器请求If-None-Match
注:
第1种方式,时间 格式复杂会难解析 和 分布式环境时间不统一,代替的方案是 优先使用
ETag
。
2.4 重新加载
1. 重新加载(reload)
不判断 响应缓存状态,直接 验证流程。
和 Chrome 浏览器Ctrl+R
刷新 效果相同。
请求时,使用下面 Headers:
Cache-Control: max-age=0;
If-None-Match: xxx;
If-Modified-Since: xxx;
max-age=0
表示 不使用存储的响应,发送 验证 请求。
- 当资源未过期,服务端返回
304 Not Modified
,则浏览器 取缓存; - 资源过期,服务端 返回
200
,直接返回 响应数据。
Android手动设置重新加载:
-
loadUrl(url, additionalHttpHeaders)
方法,添加
Cache-Control: max-age=0
header 来设置 缺省 缓存策略,实现加载最新。 -
WebView.reload()
方法调用,则会 自动添加max-age=0
控制重新加载。
注:Android WebView 请求时,默认可能会覆盖 UA、缓存、接收类型等Headers。
2. 强制重新加载(force reload)
不使用缓存,也不验证,重新从服务器获取资源。
和 Chrome 的Ctrl+Shift+R
的效果相同,DevTools可看。
请求时,使用下面 Headers:
Pragma: no-cache;
Cache-Control: no-cache;
使用上述 headers
,非条件请求,可以确保 从服务端响应 200,而不是 验证 请求,是 真正的不使用缓存。
对应 Android WebView 的 CacheMode:
WebSettings.LOAD_NO_CACHE
时,对应 强制重新加载。
三、WebView 缓存清理
1. WebView.clearCache(true)
清空资源缓存
补充 Web存储 清理:
2. WebStorage.getInstace().deleteAllData()
清空 Web Storage 存储;
3. CookieManager
的 removeAllCookies()
、flush()
管理 Cookies