WebView基础三:WebView优化

来源:互联网 发布:南京奥派软件 编辑:程序博客网 时间:2024/05/29 06:28

一.优化网页加载速度

默认情况html代码下载webView后,webkit开始解析网页各个节点,发现有外部样式文件或者外部脚本文件时,

异步发起网络请求下载文件,但如果在这之前也有解析到image节点,那是比也会发起网络请求下载相应的图片。

在网络情况比较差的情况下,过多的网络请求就会造成宽带紧张,影响到CSS或js文件的加载时间,

造成页面空包loading过久,解决的办法就是告诉webview先不要自动加载图片,等页面finish后再发起图片加载。
设置webview,先禁止加载图片

webSetting websetting=webview.getSettings();//图片加载if(Build.VERSION.SDK_INT >= 19){    webSettings.setLoadsImagesAutomatically(true);}else {    webSettings.setLoadsImagesAutomatically(false);}

覆写webviewClient的onPageFinished()方法,页面加载结束后再加载图片

@Overridepublic void onPageFinished(WebView view, String url) {    super.onPageFinished(view, url);    if (!view.getSettings().getLoadsImagesAutomatically()) {        view.getSettings().setLoadsImagesAutomatically(true);    }}

PS:4.4以上系统在onPageFinished是在恢复加载时,如果存在多张图片引用时相同的src时,会只有一个image标签得到加载,因而对于这样的系统我们就直接加载。

二 硬件加速页面闪烁问题

4.0以上的系统我们开启硬件加速后,webview渲染页面更加快速,拖动也更加流畅,但是有个副作用就是,当webView视图

被整体遮住一块,然后突然恢复时,(比如使用SlideMenu将WebView从侧边滑出来时,)这个过渡期会出现白块同时界面闪烁。

解决这个问题的方法是在过渡期前将WebView的硬件加速临时关闭,过渡期后再开启

过度前关闭硬件加速

if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB){    mWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);}

过度后开启硬件加速

if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB){    mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);}

三.选择合适的WebView缓存

缓存机制 优势 适用场景 Dom Storage HTTP协议层支持 静态文件的缓存 web SQL Database 存储,管理负责结构数据 临时,简单数据的缓存Coolies的扩展 AppCache 方便构建离线APP 离线App,静态文件缓存,不推荐使用 IndexedDB 存储任何类型数据使用简单,支持索引 结构,关系复杂的数据存储,web SQLDatabase的替代 File System API 支持文件系统的操作 数据适合以文件进行管理的场景,Android系统还不支持

四.常用资源预加载

缓存技术能优化二次启动WebView的加载速度,那么首次加载H5页面的速度改怎么优化呢?

一次加载过程会有许多外部依赖的 JS、CSS、图片等资源需要下载,那我们能不能提前将这些资源下载好,等H5 加载时直接替换呢?

好在从 API 11(Android 3.0)开始,WebView 引入了 shouldInterceptRequest 函数,这个函数有两种重载。

public WebResourceResponse shouldInterceptRequest(WebView webView, String url) 从 API 11 引入,API 21 废弃

public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request) 从 API 21 开始引入

考虑到目前大多数 App 还要支持 API 14,所以还是使用 shouldInterceptRequest (WebView view, String url) 为例。

mWebView.setWebViewClient(new WebViewClient() {    @Override    public WebResourceResponse shouldInterceptRequest(WebView webView, final String url) {                WebResourceResponse response = null;            // 检查该资源是否已经提前下载完成。我采用的策略是在应用启动时,用户在 wifi 的网络环境下    // 提前下载 H5 页面需要的资源。            boolean resDown = JSHelper.isURLDownValid(url);        if (resDown) {                    jsStr = JsjjJSHelper.getResInputStream(url);        if (url.endsWith(".png")) {                        response = getWebResourceResponse(url, "image/png", ".png");                    } else if (url.endsWith(".gif")) {                        response = getWebResourceResponse(url, "image/gif", ".gif");                    } else if (url.endsWith(".jpg")) {                        response = getWebResourceResponse(url, "image/jepg", ".jpg");                    } else if (url.endsWith(".jepg")) {                        response = getWebResourceResponse(url, "image/jepg", ".jepg");                    } else if (url.endsWith(".js") && jsStr != null) {                        response = getWebResourceResponse("text/javascript", "UTF-8", ".js");                    } else if (url.endsWith(".css") && jsStr != null) {                        response = getWebResourceResponse("text/css", "UTF-8", ".css");                    } else if (url.endsWith(".html") && jsStr != null) {                        response = getWebResourceResponse("text/html", "UTF-8", ".html");                    }        }                // 若 response 返回为 null , WebView 会自行请求网络加载资源。                return response;            }        });private WebResourceResponse getWebResourceResponse(String url, String mime, String style) {        WebResourceResponse response = null;        try {            response = new WebResourceResponse(mime, "UTF-8", new FileInputStream(new File(getJSPath() + TPMD5.md5String(url) + style)));        } catch (FileNotFoundException e) {            e.printStackTrace();        }        return response;    }public String getJsjjJSPath() {        String splashTargetPath = JarEnv.sApplicationContext.getFilesDir().getPath() + "/JS";        if (!TPFileSysUtil.isDirFileExist(splashTargetPath)) {            TPFileSysUtil.createDir(splashTargetPath);        }        return splashTargetPath + "/";   }
原创粉丝点击