開發移動App主要有三種模式:Native、 Hybrid 和 Web App。javascript
須要注意的一點是在選擇開發模式的時候,要根據你的項目類型(圖片類?視頻類?新聞類?等),產品業務和人員技術儲備等作權衡。css
Hybrid開發模式就是既有Native開發也有Web app的開發。那咱們怎麼去肯定App中某個功能模塊使用Native仍是Web開發?它們之間若是須要接口通訊又該如何去實現呢?又該如何更好的去維護Hybrid App產品呢?html
當咱們選擇用Hybrid模式開發App時,應先熟悉項目整個框架和App各個模塊。而後將通用的,對性能要求不是那麼高的App界面可抽出來做爲web界面開發,Native直接調用。通常Hybrid App開發,App界面之間的跳轉關係由Native實現並完成,web界面主要做爲內容填充到Android和iOS的瀏覽器控件中。拉手網以前Android客戶端就是採用這種模式,Native搭一個App框架殼,裏面展現內容和網絡請求所有由web實現。因爲客戶端瀏覽器控件版本不一樣,web界面加載,渲染和緩存機制等緣由,這種模式開發的App總體在圖文比較多的狀況下體驗就不太好,甚至可能會出現意想不到的奇葩問題。 建議圖文列表,涉及到視頻等多併發和界面元素比較負責或具備很強的動畫特效的狀況優先考慮Native開發。 這方面在Android尤爲有必要,Android 4.4以前的瀏覽器控件WebView基於缺省的WebKit內核,它不一樣於Chromium所使用的Webkit內核;而在4.4以後(包括4.4)的WebView的實現被替換成Chromium WebKit內核。當咱們想讓App儘量的在低版本也能運行良好時,就須要不斷作兼容性開發和測試了,除非本身在App裏面打包編譯最新WebView源碼,相似開發一個瀏覽器。java
Android和iOS都提供了API直接調用:android
webview.loadUrl("javascript:functionName(\"" + argument + "\")");
別忘了設置 webview.getSettings().setJavaScriptEnabled(true); web
[webView stringByEvaluatingJavaScriptFromString:@"alert('hello world!')"];
Android實現js調用native方法通常是先編寫供js調用的類,而後經過添加javascripteInterface的方法,如api
webView.addJavascriptInterface(pandoInterface, "pando");
將java對象pandoInterface生成js對象pando,而後直接window.pando就能夠調用pandoInterface對象裏面的方法。須要注意的是供js調用的pandoInterface對象裏面的java方法需手動加上@JavascriptInterface註解,這個是Google爲解決安全問題引入的。瀏覽器
iOS實現js調用Native方法相對繁瑣一點。主要是iOS原生並無提供js直接調用native的方式,只能經過UIWebView相關的UIWebViewDelegate協議的方法來作攔截,並在這個方法中,根據url的協議或特徵字符串來作調用方法或觸發事件等工做。當js須要調用Native方法時,js建立一個隱藏的iframe設置或改變其src就會觸發Native攔截url事件。緩存
如安全
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL *url = [request URL]; if ([[url scheme] isEqualToString:@"someFunction") { //調用原生方法 return NO; } else { return YES; } }
不知道你們發現沒有,以上兩種方法都只是實現了js調用Native方法,可是都沒有實現js函數回調,將Native方法返回結果傳遞給js。
微信開放了不少jsApi接口,供你們直接調用微信Native的功能。經過jsApi接口和文檔咱們會發現裏面實現了Native方法執行結果回調給js。這種Hybrid App開發模式很好的利用了Native高性能,多併發的優點,將網絡請求,掃碼等複雜的邏輯或者web不可能實現的功能由Native完成,而web只是作了界面顯示效果。將微信Android安裝包解壓以後,在assets/jsapi目錄下有個80多kb的wxjs.js文件,裏面實現了微信jsApi邏輯jsbridge。下面主要簡單介紹一下這種jsbridge實現原理。
jsbridge核心難點在於如何在Native方法執行完以後將返回接口給js,而且讓js能理解傳過來的參數所表達的意思。針對這,咱們能夠在js調用Native方法之間,將js一次調用Native的惟一標示符identifier和指望Native調用完後執行的回調函數存儲在Map裏面,將identifier和其餘參數傳遞給Native,native執行完成後,將identifier和執行結果做爲參數調用js函數,在js函數裏面解析參數,獲得identifier,而後在Map裏查詢對應的回調函數,將native執行結果做爲參數傳遞進去調用。有點繞,可是巧妙的利用消息傳遞機制,實現js調用Native進行回調函數調用,同理,Native調用js函數將返回結果給Native調用也是能夠的。
Android在實現jsbridge時,早期方法也是須要iOS那樣,先給web界面建立iframe,而後經過js改變iframe src,Native方法經過shouldOverrideUrlLoading(WebView view, String url)攔截url處理。可是在Android 4.2.2系統上,這個方法在iframe src改變是,是不會觸發的。目前建議你們經過攔截js alert彈框作處理。
@Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { LogUtils.i("url:" + url+"\n message:" + message); try { String msg = URLDecoder.decode(message, "utf-8"); if (msg.startsWith(BridgeUtil.PANDO_RETURN_DATA)) { // 若是是返回數據 handlerReturnData(message); result.cancel(); return true; } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return super.onJsAlert(view, url, message, result); }
注意,onJsAlert方法攔截作處理後必定要result.cancel();否則web界面就會出現點擊沒反應的狀況。
Hybrid App涉及到html、css和js等web資源文件,當web和Native之間有相互調用時,二者之間任何一方接口變更都會致使App出現bug。
Q:
最近想本身寫個android的hybrid app,看了下大多推薦的是PhoneGap,不知道他的運行效率怎麼樣,若是以原生爲重的話,適不適合用PhoneGap?
A:
我來講說吧,其實就是mui開發最快,這是我本身實踐的結果,ionic我沒用,但是cordova我用過,由於國內沒多少人分享經驗,因此坑不少。
你作一個帶掃碼,搖一搖,地理位置追蹤,消息推送的app,這些基礎功能mui基本不用研究拿來就能用。cordova光是研究插件集成和使用就得花3天時間,中間還會有不少坑。(這個已經有半成品)
可是,cordova對於你作一個需求比較奇特的app來講很好,由於他的插件庫全。mui對這個支持比較弱。(這個試了一週後放棄)
話又說回來,若是那麼奇特需求的app在技術選型上爲何不選原生?若是非得用hybird本身用webview作就是了。學cordova的時間夠把如何原生調用js和js調用原生弄明白10次了。如今我就是這麼作的。
A:
若是對原生的部分功能要求較高的話,不推薦使用PhoneGap,雖然說如今已經很成熟,可是若是涉及到原生功能仍是不好的,我以前體驗過。。
---------------------------分------------割-------------------------------------
以上內容摘自
https://www.tuicool.com/articles/riE3Yn
感謝大神們的實踐總結~