在Android WebView的开发历史中,AppCache曾经是实现网页离线访问和资源缓存的主流方案,不过随着Web标准的更新,这一特性已经被正式弃用,现代WebView版本也不再默认支持相关功能。如果继续在项目中沿用AppCache,不仅可能导致缓存失效,还会带来兼容性和安全风险。

AppCache被弃用的核心原因
AppCache的设计存在多个先天缺陷,这也是它被Web标准废弃的主要原因。首先是缓存规则不够灵活,开发者需要在manifest文件中手动声明所有需要缓存的资源,一旦资源路径发生变化,就需要同步更新manifest,否则会出现缓存不一致的问题。其次是更新机制不透明,用户经常需要多次刷新才能获取到最新的资源,严重影响使用体验。另外,AppCache对HTTPS的支持不够完善,在多页面共享缓存的场景下容易出现资源冲突,这些问题都让它不再适合现代Web开发的需求。
主流的现代缓存替代方案
1. HTTP缓存
这是最基础也最通用的缓存方案,完全基于HTTP协议的标准头部字段实现,不需要额外的前端或客户端特殊配置。核心是通过Cache-Control、Expires、ETag、Last-Modified等头部控制资源的缓存逻辑。
服务端可以在响应头中设置缓存规则,比如静态资源可以设置较长的缓存时间,动态接口则不缓存或者设置短时间的缓存:
// Android端设置WebView的HTTP缓存路径和大小
WebSettings webSettings = webView.getSettings();
// 设置缓存模式,LOAD_DEFAULT表示根据HTTP头部规则自动处理缓存
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
// 设置缓存路径,Android 8.0及以上不需要手动设置,系统会自动管理
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
webSettings.setAppCachePath(getApplicationContext().getCacheDir().getAbsolutePath());
}
// 设置缓存大小,单位字节,这里设置为100MB
webSettings.setAppCacheMaxSize(100 * 1024 * 1024);这种方案的优势是兼容性好,所有支持HTTP协议的WebView都支持,不需要额外开发成本。缺点是缓存规则完全由服务端控制,客户端无法灵活干预,也不支持复杂的离线场景。
2. Service Worker缓存
Service Worker是现代Web标准推出的离线缓存方案,运行在浏览器后台,独立于主线程,可以拦截网络请求,实现更灵活的缓存控制,支持离线访问、资源预缓存、请求重写等高级功能。
前端需要注册Service Worker并编写缓存逻辑:
// 注册Service Worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').then(function(registration) {
console.log('Service Worker注册成功,作用域为: ', registration.scope);
}).catch(function(error) {
console.log('Service Worker注册失败: ', error);
});
});
}
// sw.js 中的缓存逻辑
const CACHE_NAME = 'webview-cache-v1';
// 预缓存的资源列表
const PRECACHE_URLS = [
'/',
'/index.html',
'/css/style.css',
'/js/main.js',
'/images/logo.png'
];
// 安装阶段预缓存资源
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(CACHE_NAME).then(function(cache) {
console.log('预缓存资源');
return cache.addAll(PRECACHE_URLS);
})
);
});
// 拦截请求,优先从缓存获取,缓存不存在再请求网络
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
if (response) {
return response;
}
return fetch(event.request).then(function(networkResponse) {
// 把新的请求结果存入缓存
return caches.open(CACHE_NAME).then(function(cache) {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
});
})
);
});在Android端需要确保WebView支持Service Worker,只需要开启相关设置即可:
WebSettings webSettings = webView.getSettings();
// 开启JavaScript支持,Service Worker依赖JS运行
webSettings.setJavaScriptEnabled(true);
// 开启Service Worker支持
webSettings.setDomStorageEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}Service Worker的优势是缓存控制非常灵活,支持离线场景,缓存更新逻辑可以自定义,是目前Web离线缓存的首选方案。缺点是需要前端配合开发,旧项目可能需要改动较多代码,同时在Android低版本WebView上可能存在兼容性问题。
3. 应用层自定义缓存
如果业务场景比较特殊,比如需要缓存的内容不是标准HTTP资源,或者需要和客户端数据进行联动,也可以自己实现应用层的缓存逻辑。核心思路是拦截WebView的资源请求,优先从本地缓存读取,缓存不存在时再发起网络请求,拿到结果后同时存入缓存。
Android端可以通过WebViewClient的shouldInterceptRequest方法拦截请求:
webView.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
String url = request.getUrl().toString();
// 只处理图片类资源的缓存,其他资源走默认逻辑
if (url.endsWith(".png") || url.endsWith(".jpg") || url.endsWith(".jpeg")) {
// 从本地缓存目录读取文件
File cacheFile = new File(getCacheDir(), "web_res/" + url.hashCode());
if (cacheFile.exists()) {
try {
InputStream inputStream = new FileInputStream(cacheFile);
String mimeType = "image/png";
if (url.endsWith(".jpg") || url.endsWith(".jpeg")) {
mimeType = "image/jpeg";
}
return new WebResourceResponse(mimeType, "UTF-8", inputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
// 缓存不存在,发起网络请求,拿到结果后存入缓存
// 实际项目中可以用OkHttp等网络库请求,这里简化为示意
new Thread(new Runnable() {
@Override
public void run() {
try {
URL netUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) netUrl.openConnection();
InputStream inputStream = connection.getInputStream();
File parentDir = new File(getCacheDir(), "web_res");
if (!parentDir.exists()) {
parentDir.mkdirs();
}
FileOutputStream outputStream = new FileOutputStream(cacheFile);
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
outputStream.close();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
return super.shouldInterceptRequest(view, request);
}
});这种方案的优势是可以完全自定义缓存规则,适配各种特殊业务场景,缺点是开发成本较高,需要自己处理缓存过期、缓存清理、并发请求等逻辑,维护成本也比较高。
不同场景的选型建议
如果是静态资源为主的普通网页,优先选择HTTP缓存,开发成本最低,兼容性最好。如果需要支持离线访问或者复杂的缓存逻辑,优先选择Service Worker方案,符合现代Web标准,后续维护更方便。如果是特殊业务场景,比如缓存内容和客户端数据强关联,或者需要缓存非标准资源,再考虑应用层自定义缓存方案。
需要注意的是,如果项目中之前使用了AppCache,迁移时可以先逐步替换,先保留旧逻辑同时对接新缓存方案,确保功能稳定后再完全移除AppCache相关代码,避免出现功能断层。
WebViewAppCache缓存策略Service_Worker修改时间:2026-06-03 15:41:57