聊聊React-Native 、Weex、QT Mobile和Flutter跨平臺技術

一、跨平臺技術簡介

跨平臺技術主要爲三類:前端

  • H5+原生(CordovaIonic微信小程序
  • JavaScript開發+原生渲染 (React NativeWeex快應用
  • 自繪UI+原生(QT for mobileFlutter)

二、Hybrid技術簡介

2.1 H5+原生混合開發

這類框架主要原理就是將APP的一部分須要動態變更的內容經過H5來實現,經過原生的網頁加載控件WebView (Android)或WKWebView(iOS)來加載(之後若無特殊說明,咱們用WebView來統一指代androidiOS中的網頁加載控件)。這樣以來,H5部分是能夠隨時改變而不用發版,動態化需求能知足;同時,因爲h5代碼只須要一次開發,就能同時在Android和iOS兩個平臺運行,這也能夠減少開發成本,也就是說,H5部分功能越多,開發成本就越小。咱們稱這種h5+原生的開發模式爲混合開發 ,採用混合模式開發的APP咱們稱之爲混合應用Hybrid APP,若是一個應用的大多數功能都是H5實現的話,咱們稱其爲Web APPvue

目前混合開發框架的典型表明有:CordovaIonic微信小程序,值得一提的是微信小程序目前是在webview中渲染的,並不是原生渲染,但未來有可能會採用原生渲染。python

2.2 混合開發技術點

如以前所述,原生開發能夠訪問平臺全部功能,而混合開發中,H5代碼是運行在WebView中,而WebView實質上就是一個瀏覽器內核,其JavaScript依然運行在一個權限受限的沙箱中,因此對於大多數系統能力都沒有訪問權限,如沒法訪問文件系統、不能使用藍牙等。因此,對於H5不能實現的功能,都須要原生去作。而混合框架通常都會在原生代碼中預先實現一些訪問系統能力的API, 而後暴露給WebView以供JavaScript調用,這樣一來,WebView就成爲了JavaScript與原生API之間通訊的橋樑,主要負責JavaScript與原生之間傳遞調用消息,而消息的傳遞必須遵照一個標準的協議,它規定了消息的格式與含義,咱們把依賴於WebView的用於在JavaScript與原生之間通訊並實現了某種消息傳輸協議的工具稱之爲WebView JavaScript Bridge, 簡稱 JsBridge,它也是混合開發框架的核心。android

總結

混合應用的優勢是動態內容是H5,web技術棧,社區及資源豐富,缺點是性能很差,對於複雜用戶界面或動畫,WebView不堪重任。web

三、React Native、Weex及快應用

3.1 React-Native

React Native (簡稱RN)是Facebook於2015年4月開源的跨平臺移動應用開發框架,是Facebook早先開源的JS框架 。算法

3.1.1 DOM樹與控件樹

文檔對象模型(Document Object Model,簡稱DOM),是W3C組織推薦的處理可擴展標誌語言的標準編程接口,一種獨立於平臺和語言的方式訪問和修改一個文檔的內容和結構。換句話說,這是表示和處理一個HTML或XML文檔的標準接口。簡單來講,DOM就是文檔樹,與用戶界面控件樹對應,在前端開發中一般指HTML對應的渲染樹,但廣義的DOM也能夠指Android中的XML佈局文件對應的控件樹,而術語DOM操做就是指直接來操做渲染樹(或控件樹), 所以,能夠看到其實DOM樹和控件樹是等價的概念,只不過前者經常使用於Web開發中,然後者經常使用於原生開發中。編程

3.1.2 React中響應式編程

  • 開發者只需關注狀態轉移(數據),當狀態發生變化,React框架會自動根據新的狀態從新構建UI。
  • React框架在接收到用戶狀態改變通知後,會根據當前渲染樹,結合最新的狀態改變,經過Diff算法,計算出樹中變化的部分,而後只更新變化的部分(DOM操做),從而避免整棵樹重構,提升性能。

值得注意的是,在第二步中,狀態變化後React框架並不會當即去計算並渲染DOM樹的變化部分,相反,React會在DOM的基礎上創建一個抽象層,即虛擬DOM樹,對數據和狀態所作的任何改動,都會被自動高效的同步到虛擬DOM,最後再批量同步到真實DOM中,而不是每次改變都去操做一下DOM。爲何不能每次改變都直接去操做DOM樹?這是由於在瀏覽器中每一次DOM操做都有可能引發瀏覽器的重繪迴流小程序

  • 重繪界面 : 若是DOM只是外觀風格發生變化,如顏色變化,會致使瀏覽器重繪界面。微信小程序

  • 迴流 : 若是DOM樹的結構發生變化,如尺寸、佈局、節點隱藏等致使,瀏覽器就須要迴流(及從新排版佈局)。瀏覽器

而瀏覽器的重繪迴流都是比較昂貴的操做,若是每一次改變都直接對DOM進行操做,這會帶來性能問題,而批量操做只會觸發一次DOM更新。

3.1.3 React Native渲染

JavaScriptCore 是一個JavaScript解釋器,它在React Native中主要有兩個做用:

  • 爲JavaScript提供運行環境。
  • 是JavaScript與原生應用之間通訊的橋樑,做用和JsBridge同樣,事實上,在iOS中,不少JsBridge的實現都是基於 JavaScriptCore 。

而RN中將虛擬DOM映射爲原生控件的過程當中分兩步:

  • 佈局消息傳遞; 將虛擬DOM佈局信息傳遞給原生;
  • 原生根據佈局信息經過對應的原生控件渲染控件樹;

React Native是原生控件渲染,因此性能會比混合應用中H5好不少,同時React Native是Web開發技術棧,也只需維護一份代碼,一樣是跨平臺框架。

3.2 Weex

Weex是阿里巴巴於2016年發佈的跨平臺移動端開發框架,思想及原理和React Native相似,最大的不一樣是語法層面,Weex支持Vue語法和Rax語法,Rax 的 DSL(Domain Specific Language) 語法是基於 React JSX 語法而創造。與 React 不一樣,在 Rax 中 JSX 是必選的,它不支持經過其它方式建立組件,因此學習 JSX 是使用 Rax 的必要基礎。而React Native只支持JSX語法。

3.2.1 快應用

快應用是華爲、小米、OPPO、魅族等國內9大主流手機廠商共同制定的輕量級應用標準,目標直指微信小程序。它也是採用JavaScript語言開發,原生控件渲染,與React NativeWeex相比主要有兩點不一樣:

  • 快應用自身不支持Vue或React語法,其採用原生JavaScript開發,其開發框架和微信小程序很像,值得一提的是小程序目前已經可使用Vue語法開發(mpvue),從原理上來說,Vue的語法也能夠移植到快應用上。

  • React Native和Weex的渲染/排版引擎是集成到框架中的,每個APP都須要打包一份,安裝包體積較大;而快應用渲染/排版引擎是集成到ROM中的,應用中無需打包,安裝包體積小,正因如此,快應用才能在保證性能的同時作到快速分發。

總結

JavaScript開發+原生渲染的方式主要優勢以下:

  • 採用Web開發技術棧,社區龐大、上手快、開發成本相對較低。

  • 原生渲染,性能相比H5提升不少。

  • 動態化較好,支持熱更新。

不足:

  • 渲染時須要JavaScript和原生之間通訊,在有些場景如拖動可能會由於通訊頻繁致使卡頓。

  • JavaScript爲腳本語言,執行時須要JIT(Just In Time),執行效率和AOT(Ahead Of Time)代碼仍有差距。

  • 因爲渲染依賴原生控件,不一樣平臺的控件須要單獨維護,而且當系統更新時,社區控件可能會滯後;除此以外,其控件系統也會受到原生UI系統限制,例如,在Android中,手勢衝突消歧規則是固定的,這在使用不一樣人寫的控件嵌套時,手勢衝突問題將會變得很是棘手。

四、 自繪製引擎

4.1 QT Mobile

自繪UI+原生。這種技術的思路是,經過在不一樣平臺實現一個統一接口的渲染引擎來繪製UI,而不依賴系統原生控件,因此能夠作到不一樣平臺UI的一致性。注意,自繪引擎解決的是UI的跨平臺問題,若是涉及其它系統能力調用,依然要涉及原生開發。這種平臺技術的優勢以下:

  • 性能高;因爲自繪引擎是直接調用系統API來繪製UI,因此性能和原生控件接近。

  • 靈活、組件庫易維護、UI外觀保真度和一致性高;因爲UI渲染不依賴原生控件,也就不須要根據不一樣平臺的控件單獨維護一套組件庫,因此代碼容易維護。因爲組件庫是同一套代碼、同一個渲染引擎,因此在不一樣平臺,組件顯示外觀能夠作到高保真和高一致性;另外,因爲不依賴原生控件,也就不會受原生布局系統的限制,這樣佈局系統會很是靈活。

不足:

  • 動態性不足;爲了保證UI繪製性能,自繪UI系統通常都會採用AOT模式編譯其發佈包,因此應用發佈後,不能像Hybrid和RN那些使用JavaScript(JIT)做爲開發語言的框架那樣動態下發代碼。
  • 開發效率低:QT使用C++做爲其開發語言,而編程須要效率是直接會影響APP開發效率的,C++做爲一門靜態語言,在UI開發方面靈活性不及JavaScript這樣的動態語言,另外,C++須要開發者手動去管理內存分配,沒有JavaScript及Java中垃圾回收(GC)的機制。

Flutter正是實現一套自繪引擎,並擁有一套本身的UI佈局系統。不過,自繪製引擎的思路並非什麼新概念,Flutter並非第一個嘗試這麼作的,在它以前有一個典型的表明,即大名鼎鼎的QT。

4.1.1 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移動開發社區過小,學習資料不足,生態很差。

  • 官方推廣不利,支持不夠。

  • 移動端發力較晚,市場已被其它動態化框架佔領(Hybrid和RN)。

  • 在移動開發中,C++開發和Web開發棧相比有着先天的劣勢,直接結果就是QT開發效率過低。

基於此四點,儘管QT是移動端開發跨平臺自繪引擎的先驅,但卻成爲了烈士。

4.2 Flutter

4.2.1 Flutter簡介

Flutter 是 Google推出並開源的移動應用開發框架,主打跨平臺、高保真、高性能。開發者能夠經過 Dart語言開發 App,一套代碼同時運行在 iOS 和 Android平臺。 Flutter提供了豐富的組件、接口,開發者能夠很快地爲 Flutter添加 native擴展。同時 Flutter還使用 Native引擎渲染視圖,這無疑能爲用戶提供良好的體驗。

  • 2017 年 Google I/O 大會上,Google 首次推出了一款新的用於建立跨平臺、高性能的移動應用框架。

  • 2018年2月,Flutter發佈了第一個Beta版本,同年五月, 在2018年Google I/O 大會上,Flutter 更新到了 beta 3 版本。

  • 2018年6月,Flutter發佈了首個預覽版本,這意味着 Flutter 進入了正式版(1.0)發佈前的最後階段。

4.2.2 跨平臺自繪引擎

Flutter與用於構建移動應用程序的其它大多數框架不一樣,由於Flutter既不使用WebView,也不使用操做系統的原生控件。 相反,Flutter使用本身的高性能渲染引擎來繪製widget。這樣不只能夠保證在Android和iOS上UI的一致性,並且也能夠避免對原生控件依賴而帶來的限制及高昂的維護成本。

Flutter使用Skia做爲其2D渲染引擎,Skia是Google的一個2D圖形處理函數庫,包含字型、座標轉換,以及點陣圖都有高效能且簡潔的表現,Skia是跨平臺的,並提供了很是友好的API,目前Google Chrome瀏覽器和Android均採用Skia做爲其繪圖引擎。

目前Flutter目前默認支持iOS、Android、Fuchsia(Google新的自研操做系統)三個移動平臺。但Flutter亦可支持Web開發(Flutter for web)和PC開發,本書的示例和介紹主要是基於iOS和Android平臺的,其它平臺讀者能夠自行了解。

4.2.3 高性能

Flutter高性能主要靠兩點來保證,首先,Flutter APP採用Dart語言開發。Dart在 JIT(即時編譯)模式下,速度與 JavaScript基本持平。可是 Dart支持 AOT,當以 AOT模式運行時,JavaScript便遠遠追不上了。速度的提高對高幀率下的視圖數據計算頗有幫助。其次,Flutter使用本身的渲染引擎來繪製UI,佈局數據等由Dart語言直接控制,因此在佈局過程當中不須要像RN那樣要在JavaScript和Native之間通訊,這在一些滑動和拖動的場景下具備明顯優點,由於在滑動和拖動過程每每都會引發佈局發生變化,因此JavaScript須要和Native之間不停的同步佈局信息,這和在瀏覽器中要JavaScript頻繁操做DOM所帶來的問題是相同的,都會帶來比較可觀的性能開銷。

4.2.3 採用Dart語言開發

這是一個頗有意思,但也頗有爭議的問題,在瞭解Flutter爲何選擇了 Dart而不是 JavaScript以前咱們先來介紹兩個概念:JITAOT

目前,程序主要有兩種運行方式:靜態編譯動態解釋

  • AOT: 靜態編譯的程序在執行前所有被翻譯爲機器碼,一般將這種類型稱爲AOT (Ahead of time)即 「提早編譯」;

  • JIT: 而解釋執行的則是一句一句邊翻譯邊運行,一般將這種類型稱爲JIT(Just-in-time)即「即時編譯」。

AOT程序的典型表明是用C/C++開發的應用,它們必須在執行前編譯成機器碼,而JIT的表明則很是多,如JavaScriptpython等,事實上,全部腳本語言都支持JIT模式。

但須要注意的是JITAOT指的是程序運行方式,和編程語言並不是強關聯的,有些語言既能夠以JIT方式運行也能夠以AOT方式運行,如JavaPython,它們能夠在第一次執行時編譯成中間字節碼、而後在以後執行時能夠直接執行字節碼,也許有人會說,中間字節碼並不是機器碼,在程序執行時仍然須要動態將字節碼轉爲機器碼,是的,這沒有錯,不過一般咱們區分是否爲AOT的標準就是看代碼在執行以前是否須要編譯,只要須要編譯,不管其編譯產物是字節碼仍是機器碼,都屬於AOT。在此,讀者沒必要糾結於概念,概念就是爲了傳達精神而發明的,只要讀者可以理解其原理便可,得其神忘其形。

4.3 Dart和JavaScript作一個對比

如今咱們看看Flutter爲何選擇Dart語言?筆者根據官方解釋以及本身對Flutter的理解總結了如下幾條(因爲其它跨平臺框架都將JavaScript做爲其開發語言,因此主要將DartJavaScript作一個對比):

開發效率高

Dart運行時和編譯器支持Flutter的兩個關鍵特性的組合:

基於JIT的快速開發週期:Flutter在開發階段採用,採用JIT模式,這樣就避免了每次改動都要進行編譯,極大的節省了開發時間;

基於AOT的發佈包: Flutter在發佈時能夠經過AOT生成高效的ARM代碼以保證應用性能。而JavaScript則不具備這個能力。

高性能

Flutter旨在提供流暢、高保真的的UI體驗。爲了實現這一點,Flutter中須要可以在每一個動畫幀中運行大量的代碼。這意味着須要一種既能提供高性能的語言,而不會出現會丟幀的週期性暫停,而Dart支持AOT,在這一點上能夠作的比JavaScript更好。

快速內存分配

Flutter框架使用函數式流,這使得它在很大程度上依賴於底層的內存分配器。所以,擁有一個可以有效地處理瑣碎任務的內存分配器將顯得十分重要,在缺少此功能的語言中,Flutter將沒法有效地工做。固然Chrome V8的JavaScript引擎在內存分配上也已經作的很好,事實上Dart開發團隊的不少成員都是來自Chrome團隊的,因此在內存分配上Dart並不能做爲超越JavaScript的優點,而對於Flutter來講,它須要這樣的特性,而Dart也正好知足而已。

類型安全

因爲Dart是類型安全的語言,支持靜態類型檢測,因此能夠在編譯前發現一些類型的錯誤,並排除潛在問題,這一點對於前端開發者來講可能會更具備吸引力。與之不一樣的,JavaScript是一個弱類型語言,也所以前端社區出現了不少給JavaScript代碼添加靜態類型檢測的擴展語言和工具,如:微軟的TypeScript以及Facebook的Flow。相比之下,Dart自己就支持靜態類型,這是它的一個重要優點。

Dart團隊就在你身邊

看似不起眼,實則舉足輕重。因爲有Dart團隊的積極投入,Flutter團隊能夠得到更多、更方便的支持,正如Flutter官網所述「咱們正與Dart社區進行密切合做,以改進Dart在Flutter中的使用。例如,當咱們最初採用Dart時,該語言並無提供生成原生二進制文件的工具鏈(這對於實現可預測的高性能具備很大的幫助),可是如今它實現了,由於Dart團隊專門爲Flutter構建了它。一樣,Dart VM以前已經針對吞吐量進行了優化,但團隊如今正在優化VM的延遲時間,這對於Flutter的工做負載更爲重要。」

技術類型 UI渲染方式 性能 開發效率 動態化 框架表明 H5+原生 WebView渲染 通常 高 支持 Cordova、Ionic JavaScript+原生渲染 原生控件渲染 好 中 支持 RN、Weex 自繪UI+原生 調用系統API渲染 好 Flutter高, QT低 默認不支持 QT、Flutter

總結

技術類型級 UI渲染方式 性能 開發效率 動態化 框架表明
H5+原生 WebView渲染 通常 支持 Cordova、Ionic
JavaScript+原生渲染 原生控件渲染 支持 RN、Weex
自繪UI+原生 調用系統API渲染 F 高 QT低 默認不支持 QT、Flutter

上表中開發語言主要指UI的開發語言。而開發效率,是指整個開發週期的效率,包括編碼時間、調試時間、以及排錯、兼容時間。

動態化:主要指是否支持動態下發代碼是否支持熱更新

值得注意的是:Flutter的Release包默認是使用Dart AOT模式編譯的,因此不支持動態化;

可是Dart還有JITsnapshot運行方式,這些模式都是支持動態化的。

相關文章
相關標籤/搜索