美團打車業務很早就在美團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)官方微信公衆號。