原生開發指的是純原生應用程序(簡稱App)開發,是在Android、iOS等移動平臺上利用官方提供的開發語言、開發類庫以及開發工具等進行App開發。好比Android App就是指使用Java或Kotlin開發語言在Eclipse或Android Studio的開發工具上直接調用Android SDK API開發的App;而iOS App就是指經過Objective-C或Swift開發語言在Xcode的開發工具上直接調用iOS SDK API開發的App。前端
原生App開發表明着較好的用戶體驗和更快更高的性能,可是原生App的可移植性比較差,特別是一款原生App,Android和iOS都要各自開發,一樣的邏輯、界面都要寫兩套。vue
主要優勢:react
主要缺點:git
在移動互聯網發展初期,業務場景並不複雜,原生開發還能夠應對產品需求迭代。但近幾年,隨着物聯網時代到來,移動互聯網高歌猛進、突飛猛進,在不少業務場景中,傳統的純原生開發已經不能知足日益增加的業務需求。github
主要表如今:web
所以針對純原生開發主要面臨的動態化和開發成本這兩個問題,誕生了一些跨平臺的動態化框架。算法
這類框架主要原理是將App的一部分須要動態變更的內容經過H5來實現,使用原平生臺的網頁加載控件WebView(Android)或WKWebView(iOS)來加載。這樣一來,H5部分是能夠隨時改變而不用發版的,並且能知足動態化需求,同時,因爲H5代碼只須要一次開發,就能在Android和iOS兩個平臺上運行,這也能夠減小開發成本,也就是說H5部分功能越多,開發成本就越小,咱們稱這種H5+原生的開發模式爲混合(Hybrid)開發,採用混合模式開發的App稱之爲混合應用或Hybrid App,若是一個App的大多數功能都是H5實現的話,咱們稱其爲Web App。apache
目前混合開發框架的典型表明有:淘寶、Cordova和Ionic以及微信小程序等,值得一提的是微信小程序目前是在WebView中渲染的,但未來有可能會採用原生渲染。編程
綜上所述,原生開發能夠訪問平臺所有功能,但混合開發中,H5代碼是運行在WebView中,而WebView實質上就是一個瀏覽器內核,其JavaScript依然運行在一個權限受限的沙箱中,因此對於大多數系統的訪問能力都受到了限制,如沒法訪問文件系統、不能使用藍牙等。因此,對於H5不能實現的功能,都須要原生去作。而混合框架通常都會在原生代碼中預先提供一些給JavaScript訪問系統能力的API,而後暴露給WebView以供JavaScript調用,這樣一來,WebView就成爲了JavaScript與原生API之間通訊的橋樑,主要負責JavaScript與原生之間傳遞調用消息,而消息的傳遞必須遵照一個標準的協議,它規定了消息的格式與含義,咱們把依賴於WebView的,用於在JavaScript與原生之間通訊並實現了某種消息傳輸協議的工具稱之爲WebView JavaScript Bridge(簡稱JsBridge),它也是混合開發框架的核心。小程序
示例:Javascript調用原生API獲取手機型號
下面咱們以Android爲例,實現一個獲取手機型號的原生API供JavaScript調用。在這個示例中將展現JavaScript調用原生API的流程,讀者能夠直觀的感覺一下調用流程。咱們選用Github上開源的dsBridge(Android版、iOS版)來進行通訊。dsBridge是一個支持同步調用的跨平臺的JsBridge,此示例中只使用其同步調用功能。
1.首先在原生中實現獲取手機型號的API
class JSAPI{
@JavascriptInterface
public Object getPhoneModel(Object msg) {
return Build.MODEL;
}
}
複製代碼
2.將原生API經過WebView註冊到JsBridge中
import wendu.dsbridge.DWebView
...
//DWebView繼承自WebView,由dsBridge提供
DWebView dwebView= (DWebView) findViewById(R.id.dwebview);
//註冊原生API到JsBridge
dwebView.addJavascriptObject(new JSAPI(), null);
複製代碼
3.在JavaScript中調用原生API
var dsBridge=require("dsbridge")
//直接調用原生API `getPhoneModel`方法
var model=dsBridge.call("getPhoneModel");
//打印機型
console.log(model);
複製代碼
上面示例演示了JavaScript調用原生API的過程,一樣的,通常來講優秀的JsBridge也支持原生調用JavaScript,dsBridge也是支持的,若是您感興趣,能夠去Github dsBridge(Android版、iOS版)項目主頁查看。
混合應用的優勢是動態內容是H5,新功能增長、Bug的修復完無需讓App再次發版,Web技術棧、社區及資源豐富,缺點就是性能很差,對於複雜用戶界面或動畫,WebView不堪重任。
目前市面上流行的JavaScript開發+原生渲染的跨平臺框架有快應用、Weex、React Native(簡稱RN)。
因爲RN和React原理相通,而且Flutter也是受React啓發,不少思想也都是相通的,萬丈高樓平地起,咱們有必要深刻了解一下React原理,React是一個響應式的Web框架,我麼先了解兩個重要的概念:DOM樹與響應式編程。
文檔對象模型(Document Object Model,簡稱DOM),是W3C組織推薦的處理可擴展標誌語言的標準編程接口,一種獨立於平臺和語言的方式訪問和修改一個文檔的內容和結構。換句話說,這是表示和處理一個HTML或XML文檔的標準接口。簡單來講,DOM就是文檔樹,與用戶界面控件樹對應,在前端開發中一般指HTML對應的渲染樹,但廣義的DOM也能夠指Android中的XML佈局文件對應的控件樹,而術語DOM操做就是指直接來操做渲染樹(或控件樹),所以,能夠看到其實DOM樹和控件樹是等價的概念,只不過前者經常使用於Web開發中,然後者經常使用於原生開發中。
React中提出一個重要思想:狀態改變則UI隨之自動改變,而React框架自己就是響應用戶狀態改變的事件而執行從新構建用戶界面的工做,這就是典型的響應式編程方式,下面咱們總結一下React中響應式原理:
值得注意的是,在上述第二步中,狀態變化後React框架並不會當即去計算並渲染DOM樹的變化部分,相反,React會在DOM的基礎上創建一個抽象層,即虛擬DOM樹,對數據和狀態所作的任何改動,都會被自動且高效的同步到虛擬DOM中,最後再批量同步到真實DOM中,而不是每次改變都去操做一下DOM。爲何不能每次改變都直接去操做DOM樹?這是由於在瀏覽器中每一次DOM操做都有可能引發瀏覽器的重繪或迴流:
而瀏覽器的重繪和迴流都是比較昂貴的操做,若是每一次改變都直接對DOM進行操做,這會帶來性能問題,而批量操做只會觸發一次DOM更新。
RN是Facebook於2015年4月開源的跨平臺移動應用開發框架,是Facebook早先開源的JS框架React在原生移動應用平臺的衍生產物,目前支持iOS和Android兩個平臺。RN使用JavaScript語言,相似於HTML的JSX(即JavaScript XML——一種在React組建內部構建標籤的類XML語法),以及CSS來開發移動應用,所以熟悉Web前端開發的技術人員只需不多的學習就能夠進入移動應用開發領域。
RN是React在原生移動應用平臺的衍生產物,那二者主要的區別是什麼呢?其實,主要的區別在於虛擬DOM映射的對象是什麼?React中虛擬DOM最終會映射爲瀏覽器DOM樹,而RN中虛擬DOM會經過JavaScriptCore映射爲原生控件樹。
一、JavaScriptCore是一個JavaScript解釋器,它在RN中主要有兩個做用:
①、爲JavaScript提供運行環境;
②、是JavaScript與原生之間通訊的橋樑,做用和JsBridge同樣,事實上,在iOS中,不少JsBridge的實現都是基於JavaScriptCore。
二、RN中經過JavaScriptCore將虛擬DOM映射爲原生控件的過程分爲兩步:
①、佈局消息傳遞,將虛擬DOM佈局信息傳遞給原生;
②、原生根據佈局信息經過對應的原生控件渲染控件樹。
至此,RN便實現了跨平臺,相對於混合應用,由於RN是原生控件渲染,因此性能會比混合應用中的H5好不少,同時RN是Web開發技術棧,也只需維護一份代碼,便可在多個平臺上使用。
Weex是阿里巴巴於2016年發佈的跨平臺移動應用開發框架,思想及原理和RN相似,最大的不一樣是語法層面,RN只支持JSX語法,而Weex支持Vue語法和Rax語法,Rax的DSL語法是基於React JSX語法而創造的,與React不一樣,在Rax中JSX是必選的,它不支持經過其餘方式建立組件,因此學習JSX是使用Rax的必要基礎。
快應用是華爲、小米和OPPO以及魅族等國內9大主流手機廠商共同制定的輕量級應用標準,目標直指小程序。它也是採用JavaScript語言開發,原生控件渲染,與RN和Weex相比主要有兩點不一樣:
JavaScript開發+原生渲染的方式主要優勢以下:
JavaScript開發+原生渲染的方式主要缺點以下:
自繪UI+原生是一種跨平臺技術,這種技術的思路是:經過在不一樣平臺實現一個統一接口的渲染引擎來繪製UI,而不依賴系統原生控件,因此能夠作到不一樣平臺UI的一致性。注意,自繪引擎解決的是UI跨平臺問題,若是涉及其餘系統能力調用,依然要依賴原生開發。
自繪UI+原生的優勢以下:
自繪UI+原生的缺點以下:
也許你已經猜到Flutter就屬於這一類跨平臺技術,沒錯,Flutter實現了一套自繪引擎,並擁有一套本身的UI佈局系統。不過,自繪引擎的思路並非什麼新概念,Flutter也並非第一個嘗試這麼作的,在它以前就有一個典型的表明——QT。
QT是一個1991年由Qt Company開發的跨平臺C++圖形用戶界面應用程序開發框架。2008年,Qt Company科技被諾基亞公司收購,Qt也所以成爲諾基亞旗下的編程語言工具。2012年,Qt被Digia收購。2014年4月,跨平臺集成開發環境Qt Creator 3.1.0正式發佈,實現了對於iOS的徹底支持,新增WinRT、Beautifier等插件,廢棄了無Python接口的GDB調試支持,集成了基於Clang的C/C++代碼模塊,並對Android支持作出了調整,至此實現了全面支持iOS、Android、WP,它提供給應用程序開發者構建圖形用戶界面所需的全部功能。可是,QT雖然在PC端得到了巨大成功,備受社區追捧,然而其在移動端卻表現不佳,在近幾年,雖然偶爾能聽到QT的聲音,但一直很弱,不管QT自己技術如何、設計思想如何,但事實上終究是敗了,究其緣由,筆者認爲主要有四:
基於此四點,儘管QT是移動端開發跨平臺自繪引擎的先驅,但卻成爲了烈士。
Flutter是Google推出並開源的移動應用程序(App)開發框架,主打跨平臺、高保真、高性能。其採用Dart語言做爲開發語言,開發者能夠經過Dart語言開發Flutter App,一套代碼可同時運行在iOS和Android平臺上。Flutter提供了豐富的組件、接口,開發者能夠很快地爲Flutter添加原生擴展。
Flutter與其餘用於構建App的大多數框架不一樣,由於Flutter既不使用WebView,也不使用平臺(Android、iOS等)的原生控件。相反,Flutter使用本身的高性能渲染引擎來繪製Widget。這樣不只能夠保證在Android和iOS平臺上UI的一致性,並且也能夠避免對原生控件依賴而帶來的限制及高昂的維護成本。
Flutter使用Skia做爲其2D渲染引擎,Skia是Google的一個2D圖形處理函數庫,包含字型、座標轉換以及點陣圖都有高效能且簡潔的表現,Skia是跨平臺的,並提供了很是友好的API,目前Google Chrome瀏覽器和Android均採用Skia做爲其繪圖引擎,值得一提的是,因爲Android系統已經內置了Skia,因此Flutter在打包APK(Android應用安裝包)時,不須要再將Skia打入APK中,但iOS系統並未內置Skia,因此構建iPA時,也必須將Skia一塊兒打包,這也是爲何Flutter APP的Android應用安裝包比iOS應用安裝包小的主要緣由。
可是Flutter也有不足之處,不支持動態下發代碼和熱更新。
本章主要介紹了目前移動開發中三種跨平臺開發技術和原生開發技術,如今咱們從框架角度對比一下三種跨平臺開發技術:
技術類型 | UI渲染方式 | 性能 | 開發效率 | 動態化 | 框架表明 |
---|---|---|---|---|---|
H5+原生 | WebView渲染 | 通常 | 高 | ✔️ | Cordova、Ionic |
JavaScript+原生渲染 | 原生控件渲染 | 好 | 高 | ✔️ | RN、Weex |
自繪UI+原生 | 調用系統API渲染 | 好 | Flutter高,QT低 | 默認不支持 | QT、Flutter |
上表中動態化主要指是否支持動態下發代碼和是否支持熱更新。值得注意的是Flutter的Release包默認是使用Dart AOT(提早編譯)模式編譯的,因此不支持動態化,但Dart還有JIT(即時編譯)或snapshot運行方式,這些模式都是支持動態化的,後續會介紹。