Android WebView 加载 H5
一般流程
现状分析
Zeta Math 首页 challenge 排行榜 WebView
环境:测试环境
网络:公司内网WIFI
设备:一加8
系统:Android11
APP:Zeta Math
初始化 WebView Activity\Fragment 耗时约 110ms 首次初始化WebView约 170ms 开始请求到请求成功耗时约 680ms
环境:正式环境
网络:公司内网WIFI
设备:一加8
系统:Android11
APP:Zeta Math
初始化 WebView Activity\Fragment 耗时约 110ms 首次初始化WebView约 1240ms 开始请求到请求成功耗时约 800ms
环境:正式环境
网络:国内5G,美服VPN,967ms延迟
设备:一加8
系统:Android11
APP:Zeta Math
初始化 WebView Activity\Fragment 耗时约 110ms 首次初始化WebView约 2170ms 开始请求到请求成功耗时约 9660ms
- 注:WebView 初始化过程中像是有网络请求的操作,从 init 到 onLoadStart 回调之间的耗时时长能明显感受到受网速影响,具体原因有待考察
影响WebView加载速度的因素
- 手机硬件性能
- 网络!网络!网络!
- 浏览器内核
- 前端代码优化、JS解析效率、浏览器缓存
- ···
耗时问题
- 实例化 WebView 耗时较长
- 串行的加载流程:如图 WebView 加载的一般流程可见,一次完整的加载流程默认来说是一个串行操作
- 资源加载耗时,每次都要重新请求,增加请求耗时
WebView 预加载
全局 WebView 实例
APP 客户端启动时,初始化一个 WebView 实例池,并默认创建一个全局 WebView 实例。当页面需要打开一个 H5 前端页时,就从这里面拿出一个实例,并在实例池中继续增加一个作为备用,保持 APP 中 WebView 实例数比实际打开的H5页面多1
- 优点:节省WebView实例化时间,实现简单
- 缺点:占用额外内存开销,影响性能
后台预加载 WebView 全部内容
前端提出的方案,希望提前给到 url 以在后台提前创建 WebView 将 H5 页全部加载完成,需要时直接取出 WebView 使用
- 优点:完全在后台提前加载完成 WebView,能极大减少使用时的 loading 等待时间
- 缺点:占用极多额外内存开销和网络开销,用户可能并不会使用但却仍然加载了一个完整的前端页
WebView 秒开提速方案
缓存机制
名称 | 原理 | 优点 | 适用对象 | 说明 |
---|---|---|---|---|
浏览器缓存 | 使用HTTP协议头部字段进行缓存控制 | 支持HTTP协议层 | 存储静态资源 | Android默认实现 |
Dom Storage | 通过存储键值对实现 | 存储空间大,数据在本地,安全便捷 | 类似Cookies,存储临时的简单数据 | 类似Android中的SP |
Web SQL DataBase | 基于SQL | 利用数据库优势,增删改查方便 | 存储复杂、数据量大的结构化数据 | 不推荐使用,用IndexedDB替代 |
IndexedDB | 通过存储键值对实现(NoSQL) | 存储空间大、使用简单灵活 | 存储复杂、数据量大的结构化数据 | 集合Dom Storage和Web SQL DataBase的优点 |
AppCache | 类似浏览器缓存,以文件为单位进行缓存 | 构建方便 | 离线缓存,存储静态资源 | 对浏览器缓存的补充 |
File System | 提供一个虚拟的文件系统 | 可存储二进制数据、预加载资源和之间编辑文件 | 通过文件系统管理数据 | 目前Android不支持 |
并行流程
最理想的并行流程,将 Activity 初始化、WebView 初始化与请求主页面 html 并行,请求页面 css、js 与请求数据、资源并行,最终统一交给 WebView进行渲染,减少串行渲染造成的等待耗时。
拦截请求与共享缓存
现状:目前两端之间只专注自己的业务,前端自己通过网络请求下载资源。
Android WebViewClient 提供了一个shouldInterceptRequest
用于支持外部拦截前端页请求,WebView 每次请求网络资源时会回调该方法。
该回调方法传入了请求 url ,返回 WebResourceResponse 代表获取到的资源对象,默认返回 null,即代表由浏览器内核自己去完成网络请求。
优点:这里可以由客户端进行拦截网络请求,配置网络请求策略,共享客户端缓存或使用持久化的本地资源,节省内存及网络开销,而前端对此是完全无感知的。
预置公共模版(需前端配合)
精简并抽取公共的 JS 和 CSS 文件作为通用的页面模板(可以按业务类型来生成多套模板文件),打包到客户端中,减少每次打开 H5 需要请求的内容从而缩短总耗时。 此策略可以结合全局 WebView 实例在后台提前加载好公共模版。
复用 WebView
在全局 WebView 实例池预加载的基础上尝试增加复用 WebView 的逻辑,当 WebView 使用完毕后不再销毁,而是将正文数据清空并再次存入缓存池中,等下次直接注入新的正文数据进行复用,减少频繁创建 WebView 及加载模版带来的开销。
延迟加载(前端优化)
尽可能优先加载首屏必须内容,对于一些非首屏必需的网络请求、 JS 调用、埋点上报等,都可以后置到首屏显示后再执行。
替换浏览器内核
如腾讯X5内核,内核级加速,相较于原生 WebView 它能提速30%,节省流量20%,并还附带其他比如:更安全、防 http 劫持、视频播放优化、文件预览等功能支持。 缺点:由于是腾讯深度定制,不太灵活。
三方 WebView 提速方案
腾讯VasSonic
并行加载:将 webview 初始化和主 url html 请求分开 本地缓存:将请求的主 url 获得的 html 数据进行本地缓存 局部刷新:sonic通过和前端的约定标记分割出那些可变的块的不变的字符块,然后通过js与android交互通知原生局部刷新,缺点是需要前端支持 截流动态加载:主 html 流还没有下载完成,而 webview 已经初始化完成,这时候会中断下载过程,将已经下载的流和未下载的节点流包封装成 SonicSessionStream 传给 WebView
CacheWebView
一种自定义的缓存策略,扩大 WebView 缓存空间,强制缓存静态资源,从缓存中拿页面已经加载过的资源。