android WebView优化

Posted by alonealice on 2017-12-19

在android使用WebView去显示页面时,有一个很严重的问题就是慢。这个慢会导致页面白屏时间或者等待时间过长,严重影响用户体验。

在WebView加载页面的过程中,主要有这么几个步骤:WebView初始化,建立连接,获取数据,页面框架渲染,JS加载、解析。那么我们依次来看看这些环节有哪些可以优化的地方可以加快WebView的页面显示。

WebView初始化

App中打开WebView的第一步并不是建立连接,而是启动浏览器内核,而app中与普通浏览器中不同,当我们打开浏览器时,系统会先初始化浏览器内核,完成后,用户再输入链接。而在app中,这两部操作是连在一起的。这就导致连接网络过程时间看起来会更长,因为这当中还有WebView初始化的时间。

那怎样优化呢?目前主要有两种方案:全部WebView和代理数据请求。

使用全局WebView时,我们需要在程序启动时就初始化一个WebView,在使用时就可以直接使用该WebView,这样可以直接减少第一次初始化的时间。

但是这样做也会有问题。首先是内存:在未使用WebView时就已经预先有个WebView准备在那里了,而我们都知道,Webview本身是很耗内存的,这样就照成了内存的浪费;其次,当多个页面都需要使用WebView时,我们需要在页面跳转时清空上一个页面的痕迹,这很容易照成内存泄漏。

连接

连接部分能够优化的主要是在DNS,这部分时间很容易被人忽略。当我们请求链接时,我们首先会去DNS服务器上获取正确的ip。但是DNS会在系统级别进行缓存,对于WebView的地址,如果使用的域名与native的API相同,则可以直接使用缓存的DNS而不用再发起请求。

因此,WebView请求的地址最好与app中请求的域名统一,同理也使用在HTML页面中的各种资源的地址。

获取数据

获取数据时,如果采用普通方式输出页面,则页面会在服务器请求完所有API并处理完成后开始传输。浏览器要在后端所有API都加载完成后才能开始解析。这时就可以考虑采用chunk编码,将数据放在最后,并优先将静态内容输出。

在HTTP协议中,我们可以在header中设置 transfer-encoding:chunked 使得页面可以分块输出。如果合理设计页面,让head部分都是确定的静态资源版本相关内容,而body部分是业务数据相关内容,那么我们可以在用户请求的时候,首先将Web API可以确定的部分先输出给浏览器,然后等API完全获取后,再将API数据传输给浏览器。

这样虽然在后端时间上并没有区别,但是可以提升首字节速度,从而让前端加载资源和后端加载API不互相阻塞。

页面框架渲染

一般来说HTML在开始接收到返回数据的时候就开始解析HTML并构建DOM树。如果没有JS阻塞的话一般会相继完成。当中遇到CSS时,并不会停止解析,而是会继续往下解析,而遇到内联的JS时,一般也能很快执行完。但是,当两者同时出现时,就会出现问题。

当CSS后面有JS,则会阻塞JS的执行,直到CSS加载完成(即便JS是内联的脚本),从而间接阻塞HTML的解析。

因此在优化时,CSS的加载会在HTML解析到CSS的标签时开始,所以CSS的标签要尽量靠前,但是,CSS链接下面不能有任何的JS标签(包括很简单的内联JS),否则会阻塞HTML的解析,如果必须要在头部增加内联脚本,一定要放在CSS标签之前。

JS加载、解析

JS框架的初始化,数据的请求,逻辑的处理都是需要消耗资源和时间的,这种情况在低端手机上尤其明显。所以在app中使用的框架,要尽可能的轻量。而JS代码的编译和执行中往往会有缓存,同App中网页尽量统一框架。

参考

本文参考WebView性能、体验分析与优化,当中还有更加详细的分析和数据。