与webview打交道中踩过的那些坑
随着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打交道中踩过的那些坑的更多相关文章
- 三分之一的程序猿之社交类app踩过的那些坑
三分之一的程序猿之社交类app踩过的那些坑 万众创新,全民创业.哪怕去年陌生人社交不管融资与否都倒闭了不知道多少家,但是依然有很多陌生人社交应用层出不穷的冒出来.各种脑洞大开,让人拍案叫起. 下面我们 ...
- 【Fine原创】JMeter分布式测试中踩过的那些坑
最近因为项目需要,研究了性能测试的相关内容,并且最终选用了jmeter这一轻量级开源工具.因为一直使用jmeter的GUI模式进行脚本设计,到测试执行阶段工具本身对资源的过量消耗给性能测试带来了瓶颈, ...
- 美团在Redis上踩过的一些坑-目录(本人非美团)(转)
来自:http://carlosfu.iteye.com/blog/2254154 分为5个部分: 一.周期性出现connect timeout 二.redis bgrewriteaof问 ...
- 安装python爬虫scrapy踩过的那些坑和编程外的思考
这些天应朋友的要求抓取某个论坛帖子的信息,网上搜索了一下开源的爬虫资料,看了许多对于开源爬虫的比较发现开源爬虫scrapy比较好用.但是以前一直用的java和php,对python不熟悉,于是花一天时 ...
- [原创]阿里云RocketMQ踩过的哪些坑
由于公司的最近开始使用RocketMQ来做支付业务处理, 便开启了学习阿里云RocketMQ的学习与实践之路, 其中踩了不少的坑, 大部份是由于没有仔细查看阿里云的技术文档而踩的坑. 但是有一个非常大 ...
- Spring Cloud 升级最新 Finchley 版本,踩了所有的坑!
Spring Boot 2.x 已经发布了很久,现在 Spring Cloud 也发布了 基于 Spring Boot 2.x 的 Finchley 版本,现在一起为项目做一次整体框架升级. 升级前 ...
- Redis上踩过的一些坑
来自: http://blog.csdn.net//chenleixing/article/details/50530419 上上周和同事(龙哥)参加了360组织的互联网技术训练营第三期,美团网的DB ...
- Android Camera开发经验总结以及踩过的那些坑
写在开头 需求方:上传试卷的时候,用户自己拍的照片有很多问题.如:不清晰.图片歪了.错误图片等.我们要是能够对拍摄照片进行识别处理就好了,能够裁切矫正就更好了,最好可以像二维码扫描一样,直接识别处理- ...
- 细说分布式Redis架构设计和踩过的那些坑
细说分布式Redis架构设计和踩过的那些坑_redis 分布式_ redis 分布式锁_分布式缓存redis 细说分布式Redis架构设计和踩过的那些坑
随机推荐
- 123. Best Time to Buy and Sell Stock (三) leetcode解题笔记
123. Best Time to Buy and Sell Stock III Say you have an array for which the ith element is the pric ...
- archive成功了,但是在输出ipa时要求有账号密码
archive成功了,但是在输出ipa时要求有账号密码 可以通过命令行方式输出,绕开账号检查1.进入Windows-Organizer-Archives,找到要输出的scarchive列表项:2.右键 ...
- css 3 动画
1.transition,其作用是:平滑的改变CSS的值.无论是点击事件,焦点事件,还是鼠标hover,只要值改变了,就是平滑的,就是动画. transition 属性介绍: transition-p ...
- java-关于浏览器的判断
一.判断是手机还是电脑浏览器 public final static String[] agent = { "Android", "iPhone", " ...
- 18.safari 安装后flash还是提示安装 flash,视频不能播放
第一步: safari---->偏好设置(首先安装最新Mac adobe flash) 第二步: 第三步:点击进入 第四步:再次打开safar,大功告成!
- redis命令总结
Redis命令总结 redis 127.0.0.1:6379> info #查看server版本内存使用连接等信息 redis 127.0.0.1:6379> client list ...
- IQD文件模板以及cs7g.ini信息
COGNOS QUERY STRUCTURE,1,1 DATABASE, cognos TITLE,test BEGIN SQL { select time, city_id, city_name, ...
- iOS 取绝对值函数
1.abs(a) 处理int类型a的取绝对值 2.fabsf(a) 处理float类型a的取绝对值 3.fabs(a) 处理double类型a的取绝对值
- 移动App崩溃的测试用例设计
我们的日常生活中对移动设备越来越多的使用意味着移动App测试这个主题已成为需要考虑的一个无法避免的问题.根据最近的调查研究,用户难以容忍有bug的移动App. 移动App Bug的影响是用户体验差.A ...
- springboot使用之四:错误页面404处理建议
每个项目可能都会遇到404,403,500等错误代码,如没有错误页面,则会给用户一个很不友好的界面,springboot项目同样也存在这个问题. 但在官方文档并没有相关配置信息,这就要求我们自己来实现 ...