1. 程式人生 > >Hybrid App開發設計與實現

Hybrid App開發設計與實現

關於Hybrid的一個分享總結

傳送門

一、混合開發背景及概述

隨著移動浪潮的興起,各種APP層出不窮,極速的業務擴充套件提升了團隊對開發效率的要求,這個時候使用IOS&Andriod開發一個APP似乎成本有點過高了,而H5的低成本、高效率、跨平臺等特性馬上被利用起來形成了一種新的開發模式:Hybrid APP。
作為一種混合開發的模式,Hybrid APP底層依賴於Native提供的容器(UIWebview),上層使用Html&Css&JS做業務開發,底層透明化、上層多多樣化,這種場景非常有利於前端介入,非常適合業務快速迭代,於是Hybrid火啦。
Hybrid App主要以JS+Native兩者相互呼叫為主,從開發層面實現“一次開發,多處執行”的機制,成為真正適合跨平臺的開發。Hybrid App兼具了Native App良好使用者體驗的優勢,也兼具了Web App使用HTML5跨平臺開發低成本的優勢。

目前已經有眾多Hybrid App開發成功應用,比如美團、愛奇藝、微信等知名移動應用,都是採用Hybrid App開發模式。

為什麼要引入hybrid開發

Native應對急速業務需求,APP迭代加快,頻繁的發版已難以應付
Android渠道眾多,apple store稽核週期長
純native開發效率低,開發維護成本高
不能及時修復bug,不能動態發版
相對於其他動態釋出技術,技術研發成本較低,使用語言更廣泛,社群資源更豐富

二、Hybrid開發優劣勢

三種開發模式對比

一):Native App 即 原生App開發
優點

(1)打造完美的使用者體驗
(2)效能穩定
(3)操作速度快,上手流暢
(4)訪問本地資源(通訊錄,相簿)
(5)設計出色的動效,轉場,
(6)擁有系統級別的貼心通知或提醒
(7)使用者留存率高

缺點

(1)分發成本高(不同平臺有不同的開發語言和介面適配)
(2)維護成本高(例如一款App已更新至V5版本,但仍有使用者在使用V2, V3,V4版本,需要更多的開發人員維護之前的版本)
(3)更新緩慢,根據不同平臺,提交–稽核–上線 等等不同的流程,需要經過的流程較複雜。

二):Web App 即 網頁App開發
1、特點(html css js)
2、優勢 (發版完全自控隨時更新開發成本小時間快)
3、劣勢(效能差弱網路無網路條件下體驗差)Web App其實就是寫好的一套長得像App UI介面的能夠自適應的網頁加殼。本質套webview殼子打包成App,走的都是web頁面(html css js),這種方式對於做過Web開發的開說非常輕鬆就可以做出一個屬於自己的App,因為本身來說用的就是Web的東西,所以有非常好的跨平臺的特性可以在任意平臺執行,包括髮版這方面web可以隨時部署所以不需要發版,web頁面嵌入webview開發起來速度非常快,一個人就可以輕鬆搞定,對有展示類需求的專案來說採用這種方式是最適合的,但是如果要實現的功能比較複雜的話就顯得力不從心了。
相比Native App,Web App體驗中受限於網路環境和渲染效能。
1. 網路環境,渲染效能
Web APP對網路環境的依賴性較大,因為Web APP中的H5頁面,當用戶使用時,去伺服器請求顯示頁面。如果此時使用者恰巧遇到網速慢,網路不穩定等其他環境時,使用者請求頁面的效率大打折扣,在使用者使 用中會出現不流暢,斷斷續續的不良感受。同時,H5技術自身渲染效能較弱:對複雜的圖形樣式,多樣的動效,自定義字型等的支援性不強。

因此,基於網路環境和渲染效能的影響,在設計H5頁面時,應注意以下幾點:

1.簡化不重要的動畫/動效
2.簡化複雜的圖形文字樣式
3.減少頁面渲染的頻率和次數

三) :Hybrid App 即 混合型App開發
優點

1、跨平臺
2、開發週期短、成本低
3、使用者體驗良好
4、可以即時修復bug、動態發版

缺點
1、雖然說你可以專注在介面以及互動開發上了,但是這頁會成為一個缺點,比如說要仿造一個iOS的預設設定介面,就需要大量的html以及css程式碼了,而且效果不一定和iPhone上面的介面一樣好;
2、正因為這是跨平臺的開發,所以還是這句話:相容是前端的痛。瞭解過在Android機器上面的Web開發就知道這個痛了。比如前些年在Android裝置上面寫圓角,border-radius:10px,在Android的裝置上面會出現毛邊。
3、便於除錯其實是在Web介面層的。但是實際上做Hybrid App開發的時候,你會遇到需求,進入手機的底層請求,做某些處理。比如說如果該應用有Push Notification服務的話,你就需要到底層,獲取Push Notification發生時的資料,以及做相應的互動處理。當然類似PhoneGap這類框架,已經有很好的外掛機制去幫助你解決類似的問題,當然還有Game Center之類的外掛,具體的話可以到Github去關注PhoneGap官方的賬戶,資源非常豐富

三、前端與native分工

在做Hybrid架構設計之前需要分清Native與前端的界限,首先Native提供的是一宿主環境,要合理的利用Native提供的能力,要實現通用的Hybrid平臺架構,站在前端視角,我認為需要考慮以下核心設計問題。

互動設計

Hybrid架構設計第一個要考慮的問題是如何設計與前端的互動,如果這塊設計的不好會對後續開發、前端框架維護造成深遠的影響,並且這種影響往往是不可逆的,所以這裡需要前端與Native好好配合,提供通用的介面,比如:

① NativeUI元件,header元件、訊息類元件

② 通訊錄、系統、裝置資訊讀取介面

③ H5與Native的互相跳轉,比如H5如何跳到一個Native頁面,H5如何新開Webview做動畫跳到另一個H5頁面

資源訪問機制

Native首先需要考慮如何訪問H5資源,做到既能以file的方式訪問Native內部資源,又能使用url的方式訪問線上資源;需要提供前端資源增量替換機制,以擺脫APP迭代發版問題,避免使用者升級APP。這裡就會涉及到靜態資源在APP中的存放策略,更新策略的設計,複雜的話還會涉及到伺服器端的支援。

賬號資訊設計

賬號系統是重要並且無法避免的,Native需要設計良好安全的身份驗證機制,保證這塊對業務開發者足夠透明,打通賬戶資訊。

Hybrid開發除錯

功能設計完並不是結束,Native與前端需要商量出一套可開發除錯的模型,不然很多業務開發的工作將難以繼續,這個很多文章已經接受過了,本文不贅述。

至於Native還會關注的一些通訊設計、併發設計、異常處理、日誌監控以及安全模組因為不是我涉及的領域便不予關注了(事實上是想關注不得其門),而前端要做的事情就是封裝Native提供的各種能力,整體架構是這樣的
這裡寫圖片描述

四、Hybrid互動設計

Hybrid互動有兩種:
1、native主動呼叫前端js方法主動與前端通訊
2、H5主動與native通訊是通過url schema方式進行的,首先要和native約定好通訊的schema 如:wubacst 然後根據Android和iOS不同的通訊方式來分別約定 其中Android是在通訊之前先建立一個iframe通過iframe把拼接好的url請求傳送到native或者通過攔截prompt中的訊息來和前端通訊 iOS使用了iOS8以上的wkwebview中的messageHandlers的postMessage方法直接把url請求傳送到native native接收到前端傳送的請求解析之後通過回撥函式來通知前端

兩者通訊的橋樑都是webview

4.1、Hybrid互動原理
這裡寫圖片描述
4.1.1、WKWebView+WKScriptMessageHandler實現JS與OC之間互相通訊

iOS 基於WebKit框架的中的WKWebView+WKScriptMessageHandler實現JS與OC之間互相通訊。
整體互動過程分為三步:
第一:通過- (void)addScriptMessageHandler:(id )scriptMessageHandler name:(NSString *)name,搭建JS呼叫OC的橋樑,註冊供JS呼叫的方法name;
第二:JS在呼叫OC註冊方法只需要:window.webkit.messageHandlers..postMessage()
第三:客戶端在WKScriptMessageHandler代理方法裡收到JS的呼叫,通過解析處理,並按照事先與FE約定好的的協議做方法的對映,從而達到JS事件的響應。

4.1.2、UIWebview的javaScriptcore方式
將 UIWebViewDelegate 與 UIWebView 拆分成了14類與3個協議,包含該更細節功能的實現
- (void)evaluateJavaScript:(NSString )javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError _Nullable error))completionHandler

WKWebView :

1、在效能、穩定性、功能方面有很大提升
2、更多的支援 HTML5 的特性
3、官方宣稱的高達60fps的滾動重新整理率以及內建手勢
4、Safari 相同的 JavaScript 引擎

4.2、Hybrid通訊機制

4.2.1、整體設計
這裡寫圖片描述

4.2.2、native與js通訊流程
這裡寫圖片描述

4.2.3、js與native互動流程
這裡寫圖片描述

類似於JOSNP跨域原理
APP在安裝之後會註冊私有協議到OS,瀏覽器自身不能識別的協議時,會將連結拋給OS,轉為APP處理
比如itunes://開頭的連結是Apple Store的私有協議,支付寶的私有協議alipay://,騰訊的tencent://等等
固定協議:webview.loadUrl(“javascript: alert(‘hello world’)”);

五、互動協議設計

5.1、API式互動
呼叫native API介面方式和我們請求服務端的ajax方式類似,都是前端主動去傳送一個請求,被接收處理後返回回撥
這裡寫圖片描述

5.2、互動資料格式約定
混合開發中互動種類繁多,如何做到通用
以58同城車商通app為例:
頁面跳轉型別

wubacst://jumppage/…?query=…

native元件處理型別

wubacst://handlejs/…?query=…

5.3、前端協議封裝

前面提到過,Android和iOS對於前端的互動是有區別的,雖然都是採用URL攔截的方式,但是具體的方式是不一樣的;iOS採用WKwebview中的messageHandlers方法,而Android採用類似ajax一樣的請求;但是對於業務放來說,在和native通訊時是不區分端的,這就需要封裝一個互動協議的API來提供給業務方,在協議API中來區分處理Android和iOS的互動;

處理原始碼如下:

//區分處理Android和iOS
  _nativeBridge: function(param) {
        "android" == this.os ? this._andr4Native(param) : 
        "ios" == this.os ? this._ios4Native(param) : "ipad" == this.os && this._ios4Native(param)
    },

Android客戶端處理

_createIframe: function() {
        var iFrame;
        return iFrame = document.createElement("iframe"),
            iFrame.setAttribute("style", "display:none;"),
            iFrame.setAttribute("height", "0px"),
            iFrame.setAttribute("width", "0px"),
            iFrame.setAttribute("frameborder", "0"),
            iFrame
    }
 //開始是使用iframe和Android客戶端通訊 後來改成了prompt   
 _andr4Native: function(param) {
        var host = param.host;
        var path = param.path;
        var query = param.query;
        query = JSON.stringify(query)
        //3.5.0以上版本Android端都走新的攔截方式
        var url = "wubacst://" + host + "/" + path + "?query=" + encodeURIComponent(query);
        if(this._versionCompare(this._getVersion(),'3.5.0')){
            window.prompt(url)
        }else{
            if (!this.domReady)
            return void this.actionPreQueue.push(param);
        this.andrFrame = this._createIframe(),
            this.andrFrame.src = "wubacst://" + host + "/" + path + "?query=" + encodeURIComponent(query),
            document.body.appendChild(this.andrFrame),
            this.andrFrame = null
        }

    }

iOS客戶端處理

//messageHandlers上繫結的WBcheshangtong物件是和iOS約定好的
_ios4Native: function(param) {
        var host = param.host;
        var path = param.path;
        var query = param.query;
        query = JSON.stringify(query);
        var url = "wubacst://" + host + "/" + path + "?query=" + encodeURIComponent(query);
        if (window.webkit) {
            try {
                window.webkit.messageHandlers.WBcheshangtong.postMessage(url);
            } 
        }
    }

處理好底層互動之後,在根據業務的不同,前端封裝一些通用的協議,如:
這裡寫圖片描述

整個通訊協議API如下:

app58.prototype = {
     init: function() {},
 _nativeBridge: function(param){},
_ios4Native: function(param){},
_andr4Native: function(param){},
_createIframe: function(){},
loadPage: function(path, url, jumpParameter,title,titleColor,isDestoryBeforePage){}
...
}
var WBAPP = new app58(window.app_config || null)
六、問題總結

6.1、iOS cookie丟失問題
目前來說WKwebview還不是那麼穩定,經常會出現前端cookie丟失問題,一下是本人在開發過程中解決問題的一個過程:
這裡寫圖片描述
最終是用hookAjax來實現的
hookAjax的原理就是攔截所有的網路請求,代理send方法實現自己的目的
這裡寫圖片描述
有興趣的可以去看看hookajax 這裡就不再詳細講解了

6.2、Android通訊協議重複提交
由於Android使用的是iframe傳送請求和Android客戶端進行互動的,在前端使用canvas時,iframe重複執行,導致前端重複提交協議,目前換成了prompt互動;在開發過程中有遇到這種問題的小夥伴,歡迎留言。