美团打车业务很早就在美团App与点评App中提供了服务入口,并在技术上采用了H5与Native的混合开发技术。随着业务上线,有用户反馈咱们的地图性能有一些问题,缘由是咱们打车地图使用的是Web版的地图(经过腾讯地图JavaScript API),业内同类产品使用的是Native版的地图SDK,Native地图相比Web地图具备自然的性能优点,因此美团打车地图从首屏地图加载到后续的地图操做体验都有必定差距。前端
为了改善打车业务的地图体验,咱们想到的方案是在展现地图的部分使用Native地图,而非地图部分使用H5页面来显示,这样既能追平与竞品的地图性能差距,又能充分发挥H5的开发效率。这种方案乍一看彷佛是传统的Hybrid开发,没什么难度与新奇。好比地图使用预先内置到App中的地图SDK实现,H5与Native的交互使用业界成熟的JSBridge技术。但从打车业务角度来看,由于打车业务有不少功能入口须要漂浮在地图之上,如起终点卡片、用户中心入口等,这种漂浮功能在技术上并不容易实现,并且还要保证用户触摸动做在漂浮元素与地图上发生时,分别派发给各自的事件系统,Hybrid技术在这方面没有经验能够借鉴。数组
带着这些挑战,咱们进行一系列的尝试与试验,最终将问题解决并封装出咱们打车业务的地图调用框架,咱们称之为Native地图与Web融合框架(下文简称融合框架)。在这个过程当中,咱们总结出了一些经验,但愿能给从事相关研究的同窗带来一些帮助。微信
基于混合技术开发体系,咱们研究了市面上大部分H5页面与Native地图的应用场景,主要分为以下两类:框架
通过分析后,咱们发现这两种形式都没法知足打车业务场景的需求,由于目前市面上主流的打车业务场景由4部分构成,以下图所示:异步
上文第一类,H5页面与Native地图分别位于两个独立页面中,只能知足部分地图场景的需求,没法布局为上图H5与地图同框显示的效果。ide
上文第二类,实现这样的布局须要多个WebView才能实现,存在以下缺点:函数
调研结论是:市面上现存技术都没法知足打车场景的需求。工具
基于打车场景的特殊性,咱们作了一个大胆的假设:把页面分为2层,下层是Native地图层,布满屏幕;上层是WebView层,彻底覆盖到Native地图层之上,以下图所示:布局
咱们指望的效果是:性能
具体实现思路有以下几点,参照下图:
为了验证想法是否正确,咱们首先经过Android平台开发出Demo,验证这种分层智能传递消息的作法是可行的,该方案最大优势是兼顾了H5的开发效率与Native地图的高性能特性,很是符合美团业务地图场景的需求。为了让想法落地时更规范、更系统,咱们进行了以下的框架设计。
先介绍一个“热区数据”的概念,下图(3.2节)在手势分发层存在着消息分发热区数据部分,下文简称热区数据。热区数据是针对上层WebView的一个概念,只对WebView层有效,对下层Native地图层无效。若是用户点击屏幕事件想让H5来捕获处理,能够在屏幕区域内设置一个逻辑上的矩形区域,如:[0, 0, 50, 50](上图左上角区域),这个数据被称为热区数据。
咱们经过编写代码逻辑,控制手势消息分发的策略,若是手势消息发生在热区数据矩形范围内,咱们把消息发送给WebView处理,不然发送给Native地图处理。如上图所示,能够在同一屏幕内设定多个热区,[0, 0, 50, 50]、[430, 0, 50, 50]、[0, 200, 480, 200],热区的格式能够本身定义,咱们这里采用的基于WebView组件左上角为原点的像素坐标格式:[left, top, width, height]。
手势消息分发给WebView层流程
主要为上图1-->2-->3-->4过程,以下:
手势消息分发给Native地图层流程
主要为上图 5-->6-->7过程,以下:
热区数据的动态更新策略
由于打车业务底部的面板高度是可伸缩的,因此底部的热区数据并非静止不动的,须要考虑热区数据也要随着DOM元素的拉伸作同步调整。能够经过在WebView H5层监控DOM的变化,DOM元素发生变化时,获取变化后的DOM元素位置、大小,格式化为热区数据,并更新到消息分发热区数据部分。由于拉伸动做是一个连续的动画效果,为了高效,咱们只在动画结束的那一刻更新热区数据,中间过渡期不作处理。此总体流程为:2-->3-->4。
这部分功能须要Native端同窗实现,包括iOS与Android。两端分别在启动App时设置三层内容,最上层是手势触摸事件接收层,中间是WebView层(背景设置透明),最下层是Native地图层(如腾讯地图SDK)。用数组记录当前热区数据,当手势分发层有事件发生时,经过Touch事件获取手指位置信息,遍历热区数组判断手指位置是否与热区的矩形相交,如相交则将消息分发给WebView层,不然分发给Native层。下边是Android与iOS消息分发关键代码:
Android分发层关键代码
@Override public boolean dispatchTouchEvent(MotionEvent event){ if(event.getAction() == MotionEvent.ACTION_DOWN) { // 分发层接收到手势触摸消息,经过dispatchService类判断手势是否落在热区内,从而肯定消息分发的对象 this.touchHandler = dispatchService.inRegion(event) ? TouchHandler.WebView : TouchHandler.MapView; } // 分发给Native地图层 if(this.touchHandler == TouchHandler.MapView) { return this.mapView.dispatchTouchEvent(event); } // 分发给WebView H5层 return super.dispatchTouchEvent(event); }
iOS分发层关键代码
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitTestView = nil; // 分发层接收到手势触摸消息,经过pointInHotspot判断手势是否落在热区内,从而肯定消息分发的对象 if ([self pointInHotspot:point]) { // 分发给WebView H5层 hitTestView = [self.WebView hitTest:point withEvent:event]; }else{ // 分发给Native地图层 hitTestView = [self.mapView hitTest:point withEvent:event]; } return hitTestView; }
该层有2个功能:
通信桥即JSBridge技术,主要实现H5与Native的信息交互,这方面的技术都已比较成熟,业界有很是多的JSBridge实现,原理也都相似,常见的有:原生对象注入到H5层、URL拦截技术,Native调用JS经常使用的内置函数stringByEvaluatingJavaScriptFromString等。美团内部有比较成熟的KNB框架,因此项目中直接使用了KNB框架。
该层在地图SDK(如腾讯地图SDK)基础上进行了封装,提供一些打车业务友好的接口,如地图基本操做、打车起终点Marker添加、接送驾司机小车动画、地图事件、各类Marker的信息弹窗等。
打车业务前端的技术栈是: Vue + VueX + Vue-Router构建的单页系统。以下图所示,页面中存在不少H5元素须要添加热区,逐个元素编写代码添加的话会很繁琐,并且页面元素的位置、大小变化时还须要同步更新热区数据,这里咱们使用了Vue中的directive(指令)来解决了此问题。
以上左右2图是用户操做时页面展现的不一样状态,很明显右图底部卡片变高了,卡片变化同时须要同步更新对应的热区数据,directive技术能够很方便解决此问题,原理以下:
调试工具使用模拟器、真机均可以,开发期间咱们使用的模拟器开发,测试期间QA使用真机验证。调试过程当中主要验证2部分功能,分别是热区的验证与地图接口验证。
热区验证
主要验证主页面设置的热区是否正确,包括是否能够点击、底部卡片是否能正常拖拉、业务功能是否正常等。由于热区数据是一串数字,形如:[0, 0, 50, 50],没法直观判断出该数据是否有误,因而咱们开发了一个可视化工具,将设置热区的元素都用红色矩形高亮显示,以下图所示,这样就能快速诊断出热区数据是否有异常。工具是使用Canvas画布实现的,画布大小与屏幕大小彻底重合,借助画布就能够将矩形热区数据在屏幕中实时绘制出来。
地图接口验证
主要是编写单元测试完成的,本项目封装了50多个地图接口,每一个接口都编写单测用例,观察入参、出参、控制台输出结果,地图展现效果是否正确等。测试主要在iOS模拟器中完成,这样方便在控制台打印一些调试信息进行诊断。
该框架在大众点评App中上线后地图体验明显提高,主要有体如今如下几个方面:
Native地图层代码接口稳定、功能丰富,基本知足地图场景的业务需求。只需首次跟版发布,后续只须要迭代H5的业务逻辑便可。
本文将WebView与Native地图组件叠加到一块儿,实现了用户手势事件智能分发的机制,解决了WebView与Native地图在同一页面内布局困难的问题。这种融合机制为打车业务提高迭代效率同时保障地图体验提供了一种有效的途径,平常业务功能上线采用H5技术迭代,Native地图做为不常更新的基础能力首次发版时安装到用户手机上,实现业务需求随时发版的能力,再也不受各大应用商店的限制,用户操做地图的体验也更加流畅。该融合框架适合如下业务场景:
美团打车技术部终端研发中心,加鹏、张斌、杨睿、邱博、海峰等。
美团打车技术部终端研发中心诚招高级前端开发工程师、前端开发专家、高级iOS工程师、高级Android工程师。咱们为美团点评用户提供优质的打车服务,是本地生活吃喝玩乐行的重要环节。欢迎各位小伙伴的加入,共同打造极致出行产品。感兴趣的同窗可投递简历至:tech@meituan.com(邮件标题注明:美团打车技术部终端研发中心)
想阅读更多技术文章,请关注美团技术团队(meituantech)官方微信公众号。