目录
webview优缺点
webview添加header
WebView的启动优化
webview的缓存,节省内存减少流量
参考文档:
app中使用h5可以使内容更新更加灵活。周期更短。并且代码量也少,是apk的体积变小。但是同时也存在性能的问题。打开白屏还有加载慢更加耗流量的问题一直存在。同时为了和服务器交互,有时候需要我们处理header(头部信息)和cookie(一般用于token的保存或者用于频次限制)。首先我们来看怎样添加header和cookie。
我们使用webview的时候更多的是直接使用如下代码:
WebView.loadUrl(url);
通过loadurl直接加载了。其实在webview类中提供了添加header的方法。其实在使用一个未知的控件之前,预先浏览一下整个控件的api是有必要的。
public void loadUrl(String url, Map additionalHttpHeaders) {
checkThread();
mProvider.loadUrl(url, additionalHttpHeaders);
}
在这里我们将要传递的header保存的map中,然后调用此方法就可以传递header。
首先看下官方文档的介绍:
CookieSyncManager在21以后已经废弃。所以开发的时候要判断下api版本。
/**
* 为指定的url添加cookie
* @param url url
* @param cookieContent cookie内容
*/
private void setCookie(String url,String cookieContent){
CookieManager cm = CookieManager.getInstance();
CookieSyncManager csm = CookieSyncManager.createInstance(this);
cm.setAcceptCookie(true);
cm.setCookie(url, cookieContent);
/* //api21以上提供了回调接口来确认cookie是否设置成功
cm.setCookie(url, cookieContent, new ValueCallback() {
@Override
public void onReceiveValue(Boolean value) {
}
});*/
if(Build.VERSION.SDK_INT >Build.VERSION_CODES.LOLLIPOP){
cm.flush();
}else {
csm.sync();
}
}
通过setCookie可以将需要传递的cookie都提交。
webview加载网页从大的方面看可以分为两部分,1是启动webview,2是H5内容的展示。所以优化也是从这两个方向入手。
缓存数据节省空间可以从2个方面入手,一个是webSetting提供的缓存接口,一个是在加载过程中通过拦截进行资源替换。在这里尤其是图片的缓存和流量,通过拦截替换会比较有效果。首先是websetting的接口,可以直接设置。
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
webSettings.setDatabaseEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setAppCacheEnabled(true);
其中websetting需要cache,appcache,数据库,dom方式缓存,其中dom存储的方式相对于cookie,提供了更强大的存储能力,程序员可以把数据保存在本地,然后在需要是获取,相对于cookie的4k或者几k的存储能力,dom的存储是5m。webview也提供了基于SQL的数据库存储方式,cachemode有如下几种:
1 LOAD_DEFAULT
默认设置,如果本地有缓存,且没有过期,那么直接用本地缓存,否则进行网络请求。
2 LOAD_CACHE_ELSE_NETWORK
这个参数表示如果有本地缓存,无论是否过期都使用本地缓存内容。如果没有再去网络请求
3 LOAD_NO_CACHE
不使用缓存,直接进行网络请求。
4 LOAD_CACHE_ONLY
只进行本地缓存加载。如果缓存没有,则加载失败。
webview在加载过程中,可以在WebViewClient中的shouldInterceptRequest(Webview view,WebResourceView request)方法进行数据拦截。在这个函数中返回WebResourceResponse,如果返回值为空那么webview会进行网络加载。如果不为空,在解析返回内容。所以我们要做的手脚就在这里。
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if(request == null){
return null;
}
// 步骤1:判断拦截资源的条件,即判断url里的图片资源的文件名
if (request.getUrl().toString().contains("logo.png")) {
//判断出需要加载的图片。
InputStream is = null;
// 步骤2:创建一个输入流
try {
is = getApplicationContext().getAssets().open("images/logo.png");
// 步骤3:获得需要替换的资源(存放在assets文件夹里)事先在/assets/images目录下
//存储logo.png
} catch (IOException e) {
e.printStackTrace();
}
// 步骤4:替换资源
WebResourceResponse response = new WebResourceResponse("image/png",
"utf-8", is);
// 参数1:http请求里该图片的Content-Type,此处图片为image/png
// 参数2:编码类型
// 参数3:存放着替换资源的输入流(上面创建的那个)
//这样就不会进行网络加载,而直接读取本地图片,这样节省流量
return response;
}
return super.shouldInterceptRequest(view, request);
}
例子中的方法只适用于H5较少,图片较少的情况,否则在assets里面放文件也会大大增加apk的体积,虽然可以改为服务器下载增量的方式解决。但是图片多的情况下仍然是有问题的。正常情况下咱们可以借助已有的图片下载框架。在这里实现图片的本地缓存。这里只是介绍一下方法原理。这样就可以减少图片的下载。从而达到快速显示和减少流量占用的目的。
1 美团团队针对webview的优化方法
2 android webview的缓存机制和优化方法