对于WebView,我相信很多开发者最直观的莫过于:打开速度比原生慢。
是的,当我们打开一个WebView页面,页面往往会加载很久,很久后才出现你所需要看到的页面。
对于一个普通用户来讲,打开一个WebView通常会经历以下几个阶段:
- 交互无反馈
- 到达新的页面,页面白屏
- 页面基本框架出现,但是没有数据;页面处于loading状态
- 出现所需的数据
WebView初始化
当App首次打开时,默认是并不初始化浏览器内核的;只有当创建WebView实例的时候,才会创建WebView的基础框架。
所以与浏览器不同,App中打开WebView的第一步并不是建立连接,而是启动浏览器内核。
于是找到了“为什么WebView总是很慢”的原因之一:
- 在浏览器中,我们输入地址时(甚至在之前),浏览器就可以开始加载页面。
- 而在客户端中,客户端需要先花费时间初始化WebView完成后,才开始加载。
而这段时间,由于WebView还不存在,所有后续的过程是完全阻塞的。
怎么优化
一 、从webview入手,减少加载时间或者说复用加载时间
全局WebView
方法:
- 在客户端刚启动时,就初始化一个全局的WebView待用,并隐藏;
- 当用户访问了WebView时,直接使用这个WebView加载对应网页,并展示。
这种方法可以比较有效的减少WebView在App中的首次打开时间。当用户访问页面时,不需要初始化WebView的时间。
当然这也带来了一些问题,包括:
- 额外的内存消耗。
- 页面间跳转需要清空上一个页面的痕迹,更容易内存泄露。
【参考东软专利 - 加载网页的方法及装置 CN106250434A】
客户端代理数据请求
方法:
- 在客户端初始化WebView的同时,直接由native开始网络请求数据;
- 当页面初始化完成后,向native获取其代理请求的数据。
此方法虽然不能减小WebView初始化时间,但数据请求和WebView初始化可以并行进行,总体的页面加载时间就缩短了;缩短总体的页面加载时间:
【参考腾讯分享:70%以上业务由H5开发,手机QQ Hybrid 的架构如何优化演进?】
还有其他各种优化的方式,不再一一列举,总结起来都是围绕两点:
- 在使用前预先初始化好WebView,从而减小耗时。
- 在初始化的同时,通过Native来完成一些网络请求等过程,使得WebView初始化不是完全的阻塞后续过程。
二、资源本地化
1、在webview的加载过程中,我们通过重写方法 shouldInterceptRequest 可以拦截到不同的请求
只需要把一些常用的资源如cs、js文件打包到apk中,然后做本地的替换,就回使用本地的资源,这样减少了重复请求的时间,优化了webview的加载时间
2、本地离线包的形式
webview 可以加载网络资源,那么也是可以加载本地的资源,在apk 启动的时候,我们可以把整个前端代码文件下载解压到本地的文件路径中,然后通过file:///...index.html 去打开本地的资源
3、拦截webview的请求,shouldInterceptRequest 不仅可以拦截资源文件,也是可以拦截html中的ajax请求,拦截请求后,可以使用android常见的okhttp或者retrofit等请求框架发起请求,可以添加需要的头信息,或者修改请求参数,然后返回response再返回给webview,这样就做到了动态修改webview中的请求信息,这里需要注意的是,post请求的body是无法拦截的到的,所以就需要把body参数放置到header中拦截,然后自己处理后再拼装即可