一、前言
最近的项目开发中接入了一些网页功能,Webview加载完成大约需要10秒左右,经过使用Charles抓包分析,发现在加载过程中出现了几个比较大的js和css文件,这些文件在没有压缩之前有15M左右,发布线上压缩有也有3M左右,这些资源严重影响了webview的加载速度,同时也带来了不好的体验。在极致情况下,web端应该去做这些优化处理,但在项目赶时间的情况下,客户端在做了这些大文件资源做了离线处理,让webview加载这些的时候从本地加载。
二、Webview拦截资源
2.1获取需要拦截的资源
//本地缓存路径,一般都放在assets目录中
private static final String PATH_WEB_RESOURCE = "www";
private List<String> offlineResource;
//获取需要的缓存文件
private List<String> fetchOfflineResource(Context context) {
AssetManager assetManager = context.getAssets();
try {
String[] res = assetManager.list(PATH_WEB_RESOURCE);
if (res != null) {
return Arrays.asList(res);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
2.2拦截处理
Webview中拦截需要 WebViewClient
setWebViewClient(new WebViewClient(){
//重写以下方法,兼容不同的版本
@Override
public WebResourceResponse shouldInterceptRequest(WebView webView, String s) {
int last = s.lastIndexOf("/");
if (last != -1) {
if (s.endsWith(".js") || s.endsWith(".css")) {
String suffix = s.substring(last);
if (offlineResource.contains(suffix)) {
String mimeType;
if (suffix.endsWith(".js")) {
mimeType = "application/x-javascript";
} else if (suffix.endsWith(".css")) {
mimeType = "text/css";
}
try {
return new WebResourceResponse(mimeType, "UTF-8", getContext().getResources().getAssets().open(PATH_WEB_RESOURCE + suffix));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return super.shouldInterceptRequest(webView, s);
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView webView, WebResourceRequest webResourceRequest) {
return shouldInterceptRequest(webView, webResourceRequest.getUrl().toString());
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView webView, WebResourceRequest webResourceRequest, Bundle bundle) {
return shouldInterceptRequest(webView, webResourceRequest.getUrl().toString());
}
});
2.3 注意事项
- WebResourceResponse中的mimeType一定要与拦截的资源做好对应关系,比如text、
- 和前端约定好这些几乎不变的资源文件名,因为前端在发布的时候会做压缩处理,会改变文件的文件名
小结
为了能够快速响应用户操作,提高用户体验,开发会探索一些优化方案来处理,同时又能够满足产品的快速迭代需求。实际项目中我们还会接入X5WebView和VasSonic来提高WebView的加载速度,其中VasSonic处理起来有点麻烦,需要H5端、服务端、APP端的同时接入