随着HTML5被越来越多的用到web APP的开发当中,webview这一个神器便日渐凸显出重要地位。简要的说,webview能够在移动应用中开辟出一个窗口,在里面显示html页面,css以及js代码也可以被解析执行,它使用的是我们熟悉的webkit内核。android和ios都有相应的API,所以写一份代码在多个平台运行的能力就是以webview为基础的。

  今天我们要聊的不是如何使用webview,而是笔者本人作为一名前端工程师,在与客户端开发人员通过webview打交道中遇到的种种神奇事件。

  事情还得从去年说起,我还是一个小白实习生的时候。当经理知道有webview这个神器之后,遂下令让android组和ios组削减工作内容,所有共同的界面均由web组提供。而web组当时处于“传统软件公司无前端”的局面,页面相当臃肿,压根不适于移动设备。于是乎,不明局势的经理指挥一个不明真相的小白实习生,带着还没使利索的jQuery,开始了所谓的Hybrid App开发。一个凄惨的故事拉开序幕,下面是在开发当中踩过的各种坑,记录下来以供备忘。

webview与设备自带浏览器一样吗?

  webview会调用系统自带的浏览器内核来解析页面。这是个真命题吗?市场上的大部分平板电脑自带浏览器为webkit内核,webview使用的也是webkit内核,并且按一个应用的大小来看也不可能自己带一个内核进去。所以是调用系统自带的是没错的了。那我在一台设备上,使用浏览器打开一个页面和使用webview打开同一页面,得到的结果会是一模一样吗?当然是废话了,都说了是调用关系。

  假如真是废话,那我也没必要记下这一点了。因为从我的实际操作情况来看,有些时候确实是不一样的。浏览器里一个样,webview里又是一个样。ipad上情况好些。在android品牌杂乱的设备上,此现象还真的出现不只一次。尤其是页面DOM结构比较复杂的时候。

  有理由怀疑我的代码不符合W3C规范啥的,但业界良心,W3C规范还是不敢违反的。所以得出结论,webview与自带浏览器解析的结果并不是完全一致,不能以为页面在浏览器中正常了,在移动设备上也就正常了。

绝对要慎用的瀑布流

  大概是两年前,瀑布流这个概念红遍大江南北,各网站纷纷效仿,相应的文章、jQuery插件层出不穷。后来真正有思想的人开始质疑,提出我们要学习的不是瀑布流的形式,而是思想,我们需要的是真正适合自己产品的东西。后来,我们经理也听说了瀑布流这个东西。。。

  加!加瀑布流!我们不要分页列表那些东西!于是小白实习生网上各种搜索,找到了当时比较流行的叫做infinitescroll的jQuery插件。各种改源码配合实现产品业务、各移动设备兼容性bug处理暂且放一边。这里要提的是与移动应用密切相关的一个问题。

  做移动开发的对闪退这种现象估计是咬牙切齿,移动应用的性能问题一直是不容小觑的。就webview来讲,当html页面的DOM元素很多,或者说层级关系较复杂时,对其的压力是相当大的。再看看我们的瀑布流,随着页面的滚动,不断往上append节点,这对webview来说压力极大,当节点数量到一定程度时,就发现页面滚动不是那么流畅,开始一卡一卡。别急,你在翻转一下屏幕试试,瞬间崩溃,界面这个花了,内容像是绘制不出来一样。因为在做横竖屏翻转时,解析引擎会进行页面的重绘,这么多的节点工作量可不小。ipad因为其优越的图像处理性能表现还不错,android设备上简直一塌糊涂。

  有什么解决办法呢?我在听一个大牛的经验分享会上曾听到,在页面滚动的时候可以通过计算,动态remove节点,保证用户能看到的地方是有内容的,其他滚动卷去的部分就直接remove掉,等滚动回来的时候再加回来。这样保证页面上的节点不会太多,性能自然提升。我没有尝试这种方案,其中的注意事项也不好说。不过大牛成功了,必然是可行的。

  总之得出一个结论,在移动设备上,要用瀑布流,一定要慎用,必须先有性能的解决办法。

响应式布局与viewport

  我们知道移动设备在渲染页面的时候,会先在一个虚拟画布上渲染,然后再缩放到设备的尺寸,比如IOS是在宽度为980px的虚拟画布上渲染。我们看一些响应式设计的文章,也会知道在页面<head>中要添加如下内容:

<meta name="viewport" content="width=device-width, initial-scale=1.0"/>

  来保证页面会按照设备的宽度进行渲染而不是使用虚拟画布。然后便可以使用响应式设计的相关技术,弹性盒子、媒体查询等,让页面适应设备宽度显示。

  然而我遇到了一个问题,因为页面结构较复杂,在横竖屏翻转的时候出现了花屏,各种显示不全,各种抽风抖动。当然是在android设备上。。。原因就是设备的宽度发生变化webview要进行页面重绘,然而在重绘的过程中,由于页面太复杂而不堪重负,绘到一半不管了。

  因为当时该页面的设计,会显示图片、音频、视频等媒体,并且是多个同时显示,进行页面精简不可行。说来惭愧,面对紧迫的时间,我只好悄悄把上面的<meta>标签删掉,让页面还是在虚拟画布上渲染,这样渲染好的页面在进行横竖屏翻转的时候,貌似是不会进行重绘的,只会由系统缩放一下,花屏的现象也不会发生了。只不过在竖屏下,页面元素明显小了。算是个下策。

  像这样的情况,个人觉的在页面设计的时候就应该考虑到,若要进行横竖屏翻转,页面尽量设计的精简清爽。不过话说回来,移动应用上的页面,精简是一直需要且必须的。

尽量不要用别人的插件

  不怕丢人的承认,我们做web App用的是jQuery,原谅我当时是个小白吧。。。如果早些知道我们的东西只需支持现代浏览器,无论如何也得试试zepto或是其他的小而轻的库。不过既然用了,还是来面对这个现实吧。

  小白的特征之一就是从素材网站收藏了好多jQuery插件,然后在项目中不假思索就用。我们的页面是先在PC上用,然后才被告知要被webview引用的。这下麻烦来了,原先使用的好好的插件,一但跑在移动设备上,各种羊癫疯发作。然后开始不遗余力的改源码,过程简直不堪回首。

  比较典型的一个,我们的页面中有富文本编辑器,当时选择的是国内的一款开源编辑器KindEditor。我没有诋毁这个项目的意思,它在PC上使用还是蛮好的。一上了平板,直接傻了,基本上废了。环视网上,没有一款为移动设备设计的编辑器。所以编辑器这东西,还是让本地代码来做比较合理。

  另一个插件用的比较痛苦的是H5视频播放的,用了mediaelement,它在官网宣称支持各浏览器各平台,然而真正效果却并非宣称的那样。在android4.0以上的设备中都有各种兼容性问题。又是一顿改源码。。。

  所以得出的结论就是,如果某个组件可以自己写出来,千万别从网上找别人的,到头来自己还得麻烦。倘若真的准备要使用,一定先做一个全方位的测评。包括能否与你的业务逻辑完美融合,能否支持你所需要的设备。

:hover伪类在移动设备上的特殊现象

  我们在做鼠标悬停效果时,经常会用到:hover,无论用在<a>标签或是其他标签,现代浏览器都能正常兼容。比如我有一个图标,在鼠标移上去之后想要一个阴影效果,可能会这样写:

.icon:hover{box-shadow:2px 2px 2px;}

  在移动设备上,是没有鼠标指针的。当用手指点击图标的时候,可以出现阴影效果,这种效果也是可以接受的。但是当点击完成后,手指离开了屏幕,图标的hover效果却没有消失,依然是带着阴影,就好像是有一个隐形的鼠标指针停留在图标上一样,实在是让人不能理解。当再点击页面的其他部分时,图标的hover效果就消失了,好像是隐形的鼠标指针移到了别的地方。

  ipad和android设备上都有此现象。为了避免此问题,css中的:hover伪类就必须利用媒体查询,只在桌面浏览器中生效。

ipad关闭屏幕造成的问题

  ipad出于节约电量的设计,关闭屏幕后浏览器中的一些线程也会暂时关闭,等到开启屏幕时再起。如果有需要持续执行的js代码,关闭屏幕后便无法工作了。比如,要用setInterval函数实现一个计时功能,每隔一秒进行时间更新。当屏幕关闭后,计时函数就不能工作了,即关闭屏幕5秒种,你的计时器也将停止5秒。

  如果是实现一些网页动态效果,这倒没什么影响。但如果你的计时器涉及到了业务逻辑,比如计的是一次考试的时间,那影响就大了。一个考生关闭屏幕后将可以使时间静止。这是不希望发生的。所以,如果代码中有用js进行计时,或其他需持续执行的任务。需要考虑到此问题。

  对于计时器,我们可以隔一段时间与服务器进行时钟同步,从而解决客户端因关闭屏幕造成的计时误差。

  顺便再加一句,使用ipad上的safari浏览器,在切换到别的标签页时,原标签中的线程也会被停掉,跟关闭屏幕一样的效果。

定位属性与重绘的纠葛

  在移动设备横竖屏翻转的时候,会进行页面的重绘,ipad图像处理性能较强,问题不大,但是形形色色的android设备性能不一,一些较差的在转屏时经常会显示不出来界面,或是出现花屏。比较明显而且严重的情况是,当页面上的元素使用了position:fixed或是position:absolute时,转屏后该元素的定位将会错乱,可能是转屏时页面所处的环境变动太大,渲染引擎计算的时候性能消耗太多,总是无法将这类元素正确显示出来。

  我的处理办法是自己让webview把这个元素再重绘一下,操作元素的属性、className,或者是设置visibility均可触发重绘行为。但这种方式也不是屡屡见效,有时候也无济于事。没办法,android就是这么奇葩,太不稳定。所以实在不行我也会这么写:

$(‘html’).css(‘visibility’,’hidden’);
setTimeout(function(){
$(‘html’).css(‘visibility’,’visible);
},100);

  我怀疑webview的重绘是否真的进行了,所以直接让页面闪烁一下,这样效果会好很多,一般情况都能重绘正确。

  再糟的情况,实在用HTML解决不了了,可以去找客户端的同学,让他们操作webview,webview也可以进行重绘或者是直接reload。

不得不说的touch事件

  在桌面浏览器上,基本的功能都是靠监听click事件来完成的,移动设备上没有鼠标指针压根就没有click这事件,不过对于这么重要的东西,引擎当然是做了相应处理。click事件在pad上可以很好的被响应。

  但正如上面提到的,小白总是会使用一些现成的插件。。我用了一个弹出窗口插件,在桌面上可以用鼠标拖动,但是在pad上却无法拖动了。移动设备上的引擎虽然对click做了很好的处理,但是对mousedown、mousemove、mouseup却没有理会,所以需要在代码中对应的加上touchstart、touchmove、touchend事件。

  有些现象是可以想出原因来的,但有些现象是那种根本就不讲道理的,我这里也不知道如何描述。大概就是当touch事件和click事件同时被监听,再加上页面结构复杂等其他因素,就会出现各种抽风行为。

  首先精简页面结构是最最重要的,没有之一。其次对于不同设备的奇异现象,我也只能想办法进行各种hack了。

明确要支持哪些设备

  这一点跟技术无关了,是一个决策问题。ipad无论是2、3、4还是mini都比较稳定,兼容问题基本没有。主要是android,系统版本从2.x到4.x不等,各种牌子:三星、华硕、联想算比较主流的,其他是像昂达、酷派、粤教云。而且各品牌还有多种型号。再加上各厂家对android系统的无节操修改,浏览器内核都改。整个现在那叫一个乱啊。

  所以在项目初期,明确要支持哪些设备是非常重要的。这样就可以针对这些设备进行兼容性的测试。而不是今天客户说要用哪个设备,我们就想办法兼容哪个设备,真是会累死。还真有这样的客户,说我们就只使用千元以下的平板,性能那真是一个蛋疼。

  经历了一番痛苦的挣扎,秉着能解决就解决,解决不了就hack的原则,项目还真按期完成了。hack写多了真是有种犯罪感啊!现在看着项目,真的有种假如上天给我再来一次机会的呐喊,不过一切都过去了。经验教训一大把,在此挑些典型的与大家共享。可能在专做移动开发的前端眼里,这些都是小儿科,但作为一个从小白走过来的程序员,这些经验还是相当重要。

与webview打交道中踩过的那些坑的更多相关文章

  1. 三分之一的程序猿之社交类app踩过的那些坑

    三分之一的程序猿之社交类app踩过的那些坑 万众创新,全民创业.哪怕去年陌生人社交不管融资与否都倒闭了不知道多少家,但是依然有很多陌生人社交应用层出不穷的冒出来.各种脑洞大开,让人拍案叫起. 下面我们 ...

  2. 【Fine原创】JMeter分布式测试中踩过的那些坑

    最近因为项目需要,研究了性能测试的相关内容,并且最终选用了jmeter这一轻量级开源工具.因为一直使用jmeter的GUI模式进行脚本设计,到测试执行阶段工具本身对资源的过量消耗给性能测试带来了瓶颈, ...

  3. 美团在Redis上踩过的一些坑-目录(本人非美团)(转)

    来自:http://carlosfu.iteye.com/blog/2254154 分为5个部分:    一.周期性出现connect timeout    二.redis bgrewriteaof问 ...

  4. 安装python爬虫scrapy踩过的那些坑和编程外的思考

    这些天应朋友的要求抓取某个论坛帖子的信息,网上搜索了一下开源的爬虫资料,看了许多对于开源爬虫的比较发现开源爬虫scrapy比较好用.但是以前一直用的java和php,对python不熟悉,于是花一天时 ...

  5. [原创]阿里云RocketMQ踩过的哪些坑

    由于公司的最近开始使用RocketMQ来做支付业务处理, 便开启了学习阿里云RocketMQ的学习与实践之路, 其中踩了不少的坑, 大部份是由于没有仔细查看阿里云的技术文档而踩的坑. 但是有一个非常大 ...

  6. Spring Cloud 升级最新 Finchley 版本,踩了所有的坑!

    Spring Boot 2.x 已经发布了很久,现在 Spring Cloud 也发布了 基于 Spring Boot 2.x 的 Finchley 版本,现在一起为项目做一次整体框架升级. 升级前 ...

  7. Redis上踩过的一些坑

    来自: http://blog.csdn.net//chenleixing/article/details/50530419 上上周和同事(龙哥)参加了360组织的互联网技术训练营第三期,美团网的DB ...

  8. Android Camera开发经验总结以及踩过的那些坑

    写在开头 需求方:上传试卷的时候,用户自己拍的照片有很多问题.如:不清晰.图片歪了.错误图片等.我们要是能够对拍摄照片进行识别处理就好了,能够裁切矫正就更好了,最好可以像二维码扫描一样,直接识别处理- ...

  9. 细说分布式Redis架构设计和踩过的那些坑

    细说分布式Redis架构设计和踩过的那些坑_redis 分布式_ redis 分布式锁_分布式缓存redis 细说分布式Redis架构设计和踩过的那些坑

随机推荐

  1. photo shop替换颜色(自己指定的颜色)

    点开"选择"-"色彩范围",在选择下拉菜单里选"取样颜色",吸取图片上的要改的颜色,"确定",左下角拾色器前景色用你希望 ...

  2. [03]APUE:文件 I/O

    [a] open #include <fcntl.h> int open(const char *path, int oflag, ... ,mode_t mode) 成功返回文件描术符, ...

  3. ajax select option 数据。为了下次方便信手拈来!!

    为了下次方便信手拈来!! 示例1 var form = document.forms["maddraddform"]; $(form.province).change(functi ...

  4. cxf+spring+数字签名开发webservice(二)

    场景         上一章中的webservice接口,因为现场正式环境的项目与外部单位网络不通,是通过前置机与外部进行数据交换,所以我们将webservice部署在前置机,在使用HttpURLCo ...

  5. python day1 变量的命名和赋值

    变量 一.变量的命名 1.不能以数字进行开头 2.不能包含特殊字符 3.不能是python内部的某些关键字 a = 123print(a)123 --------------------------- ...

  6. hdoj 1016 Prime Ring Problem

    Problem Description A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ... ...

  7. 虚拟机上安装Linux操作系统

    很久之前就知道虚拟机这个东西,也都在虚拟机上安装过Windows的操作系统和Linux的操作系统,但是一直都没有去做笔记. 最近还是比较有时间,就移除了前两天刚刚安装的Linux系统,重新安装一次,做 ...

  8. JS实现的简单横向伸展二级菜单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. BruteXSS:XSS暴力破解神器

    ×01 BruteXSS BruteXSS是一个非常强大和快速的跨站点脚本暴力注入.它用于暴力注入一个参数.该BruteXSS从指定的词库加载多种有效载荷进行注入并且使用指定的载荷和扫描检查这些参数很 ...

  10. 使用JSON Schema来验证接口数据

    最近在做一些关于JSON Schema的基建,JSON Schema可以描述一个JSON结构,那么反过来他也可以来验证一个JSON是否符合期望的格式. 如果之前看我写的<使用joi来验证数据模型 ...