技术收藏Android

Android WebView 优化汇总

2019-01-08  本文已影响21人  BKQ_SYC

目录

Html加载流程

  1. 创建并初始化WebView
  2. 下载网页所需资源文件
  3. 渲染展示网页
HTML加载流程.png

加载流程各节点耗时分析优化

加载流程结构优化

串行模式.png
并行模式.png
但,由于WebView初始化与请求网页资源操作结束时间先后无可得知。

方案:流式拦截,加入中间层来桥接内核和数据

  1. 启动子线程请求页面主资源,子线程中不断将网络数据读取到内存中。
  2. WebView初始化完成的时候,提供中间层BridgeStream来连接WebView和数据流;
  3. WebView读取数据时,中间层BridgeStream先把内存的数据读取返回后,再继续读取网络的数据。
中间件.png

通过桥接流的方式,整个内核无需等待,边加载边解析

客户端优化

如何缓存html、js、css、图片等文件,通过缓存机制,对于应用提高资源文件的加载速度、流量优化有很大意义。而具体该针对哪种资源使用哪个缓存字段,以及缓存时长设置就比较重要。若时长设置的太短,则缓存效果受影响,若时长设置过长,则不能及时获取服务器最新数据。

由于,WebView各缓存机制的缓存大小有限,时常导致最开始的缓存被清理;浏览器缓存Last-ModiedETag控制不完全,依然无法很好的避免过渡请求网页资源,因此,需要一套可控的缓存策略,来突破缓存容量过小和图片缓存策略统一的问题。

   // 1. 固定资源放到项目文件夹,如/Assets文件夹中 
   // 2. 注入JS方法
   webView.addJavascriptInterface(new JsInterface(), "JsInterface")
   private class JsInterface {
      @JavascriptInterface
      public String getLocalSrc(String src) {
           return "file://storage/emulated/0/app/file/a.jpeg"
      }
   }
   // 3. 页面加载完成时,修改图片标签
   private class MyWebViewClient extends WebViewClient {

    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        String js = "javascript:(function() {
             var objs = document.getElementsByTagName('img');
             for (var i = 0; i < objs.length; i++)  {
                  var imgUrl = objs[i].getAttribute('src'); 
                  var localUrl = window.local_obj.getLocalSrc(imgUrl); 
                  if (localUrl) { 
                      objs[i].setAttribute('src', localUrl);
                  }
             }
        })()"

        view.loadUrl(js);
    }
}
  1. 方式二、请求拦截
  webView.setWebViewClient(new WebViewClient() {
      // 为方便,此处进写Api 21以下方法,Api21 以上雷同
      @Override
      public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
           // 1. 判断拦截资源的条件
           if (url.contains("logo.gif")) {
                // 假设网页图片资源为:http://abc.com/image/logo.gif
                // 图片资源文件名为:logo.gif

                // 2. 创建输入流
                InputStream is = null

                try {
                    // 3. 获得需要替换的资源(存放在assets文件夹中)
                    is = getApplicationContext().getAssets().open("image/abc.png") 
                } catch (IOException e) {
                    e.printStackTrace()
                }

                // 4. 替换资源
                WebResourceResponse reponse = new WebResourceResponse("image/png", "utf-8", is)
                return response
           }
           return super.shouldInterceptRequest(view, url)
      }
  })

此外,客户端需要预置资源,并维护网络图片url和本地图片自检的关联,根据一定策略保证本地预置资源为最新资源。若预置资源不限于图片资源,由于html、js、css等资源容易发生变化,因此还需实现一套机制实现本地资源和服务端数据及时的更新。即服务端需要支持版本控制和资源增量下发等功能。

总结

结合手Q、网易严选、美团等其他方面优化方案,大致如下:
上一篇 下一篇

猜你喜欢

热点阅读