如何在Android客户端无需修改服务端配置设置WebView缓存过期时间
解决方案
在不修改服务端配置的前提下,Android端可以通过拦截WebView请求、自定义缓存规则的方式实现自定义缓存过期时间,具体可按以下两种方案实现:
方案1:注入自定义响应头,复用WebView原生缓存逻辑
WebView默认的缓存过期判断完全依赖服务端返回的Cache-Control、Expires等响应头,我们可以拦截WebView的资源响应,手动注入自定义的缓存规则头,即可让WebView原生缓存机制按照我们设置的过期时间执行判断,不需要自行实现缓存读写逻辑。
示例代码如下:
// 先完成WebView基础缓存配置 WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setDomStorageEnabled(true); webSettings.setAppCacheEnabled(true); String cacheDir = getApplicationContext().getCacheDir().getAbsolutePath() + "/webviewCustomCache"; webSettings.setAppCachePath(cacheDir); webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // 重写WebViewClient拦截请求,注入缓存头 webView.setWebViewClient(new WebViewClient() { @Nullable @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { // 过滤不需要自定义缓存的请求可直接返回默认逻辑 if (!"GET".equals(request.getMethod())) { return super.shouldInterceptRequest(view, request); } OkHttpClient okHttpClient = new OkHttpClient(); Request okRequest = new Request.Builder() .url(request.getUrl().toString()) .build(); try { Response okResponse = okHttpClient.newCall(okRequest).execute(); // 自定义缓存过期时间,示例设置为2小时(7200秒) Map<String, String> respHeaders = new HashMap<>(); respHeaders.put("Cache-Control", "public, max-age=7200"); // 返回注入了缓存头的响应给WebView return new WebResourceResponse( okResponse.header("Content-Type", "text/plain"), okResponse.header("Content-Encoding", "utf-8"), okResponse.code(), okResponse.message(), respHeaders, okResponse.body().byteStream() ); } catch (IOException e) { return super.shouldInterceptRequest(view, request); } } });
方案2:自行实现缓存逻辑,完全控制过期规则
如果需要针对不同类型资源设置不同过期时间、或者需要更细粒度的缓存控制,可以自行实现本地缓存池,每次拦截请求时先校验本地缓存是否存在、是否在有效期内,有效则直接返回本地缓存,否则请求网络并存入本地缓存。
示例逻辑参考:
- 初始化本地缓存目录,缓存文件命名用请求URL的MD5值,同时记录每个缓存文件的创建时间
- 拦截请求时,先判断对应缓存文件是否存在,且当前时间 - 创建时间 < 自定义过期时长
- 符合条件则直接读取本地文件构造
WebResourceResponse返回,否则走网络请求,请求成功后将内容写入本地缓存并记录创建时间
注意事项
- 上述拦截逻辑默认仅支持GET请求,POST请求需要额外处理参数传递逻辑
- 如果仅需要简单的定期清理全量缓存,也可以定时调用
webView.clearCache(false)清理所有非活跃缓存,或者遍历缓存目录删除最后修改时间超过指定时长的文件 - 如果项目本身已经使用OkHttp作为网络库,可以直接给OkHttp添加全局拦截器统一注入
Cache-Control头,不需要在WebView拦截方法中重复处理
内容的提问来源于stack exchange,提问作者mrzbn
相关产品推荐
相关产品推荐

