背景
目前,移動(dòng)開發(fā)演化出了兩種主流開發(fā)方式:原生開發(fā)和各種跨平臺(tái)開發(fā)方式高氮。原生的優(yōu)勢顯而易見:生態(tài)好(坑少),性能強(qiáng)勁穩(wěn)定顷牌,體驗(yàn)流暢,直接調(diào)用系統(tǒng)的原生能力塞淹,能滿足各種各樣的業(yè)務(wù)需求窟蓝。然而也有一些劣勢:開發(fā)成本高,Android和iOS開發(fā)語言不同饱普,每一端都需配備一個(gè)開發(fā)人員运挫,用戶體驗(yàn),版本控制也很難做到統(tǒng)一套耕,其次業(yè)務(wù)發(fā)展過于迅速的時(shí)候谁帕,原生開發(fā)往往難以跟上,主要體現(xiàn)在:1.版本更新必須通過提示用戶升級的方式冯袍,繁瑣且體驗(yàn)不是很好匈挖。2.每次更新上架應(yīng)用市場的時(shí)候都需要審核,耗時(shí)較長康愤。難以滿足業(yè)務(wù)發(fā)展的需要儡循。
因此,各種各樣的跨平臺(tái)方案就應(yīng)用而生征冷。
跨平臺(tái)方案
當(dāng)前的跨平臺(tái)方案從原理上分大致可以分為三類择膝,以下分別介紹下這三類方案的基本原理及優(yōu)缺點(diǎn)。
webview方案
一種是H5+webview检激,就是利用原生的webview控件提供一個(gè)瀏覽器功能肴捉,所有UI控件都是h5寫成的前端控件,應(yīng)用直接像訪問網(wǎng)頁一樣從服務(wù)端加載控件的樣式和數(shù)據(jù)叔收,然后通過瀏覽器引擎加載到屏幕上齿穗。由于webview不能直接調(diào)用原生功能,因此需要使用原生語言和javaScript定義一套互相調(diào)用的協(xié)議今穿,來調(diào)用系統(tǒng)能力缤灵。其主要代表就是Hybrid和微信小程序。
這種方案由于直接使用前端技術(shù),原生能力只需要封裝一套就足夠了腮出,因此大大節(jié)省了開發(fā)成本帖鸦,開發(fā)便捷,小的版本更新也直接在服務(wù)端更改代碼即可胚嘲,還可以兼顧兩端的用戶體驗(yàn)作儿。然而最大的缺點(diǎn)就是性能低下,涉及到數(shù)據(jù)交互量大的應(yīng)用場景或動(dòng)畫或者游戲應(yīng)用就完全行不通馋劈,頁面卡頓厲害攻锰,而且會(huì)頻繁的從服務(wù)端請求數(shù)據(jù),耗費(fèi)流量妓雾。
Js+原生渲染
第二種是Js+原生渲染娶吞,就是通過js描繪出各種UI控件,然后利用中間層將UI控件轉(zhuǎn)化成原生控件械姻,通過原生的方式將頁面渲染出來妒蛇,網(wǎng)絡(luò)通信和原生能力也通過中間層來調(diào)用原生能力。主要代表就是reactNative和weex楷拳。
reactNative
reactNative是Facebook于2015年4月開源的跨平臺(tái)移動(dòng)應(yīng)用開發(fā)框架绣夺,是Facebook開源的JS框架React在原生移動(dòng)應(yīng)用平臺(tái)的衍生物。React Native使用了react的設(shè)計(jì)模式欢揖,但是其UI渲染陶耍、動(dòng)畫效果、網(wǎng)絡(luò)請求等均是由原生來實(shí)現(xiàn)的她混。開發(fā)者編寫JS代碼烈钞,通過React Native的中間層轉(zhuǎn)化為原生控件,并進(jìn)行操作产上。也就是說通過JS代碼來調(diào)用原生的組件棵磷,從而實(shí)現(xiàn)相應(yīng)的功能。 React Native實(shí)現(xiàn)跨平臺(tái)的功能晋涣,主要由Java仪媒、C++和Javascript三層所構(gòu)成的。其中谢鹊,C++實(shí)現(xiàn)的動(dòng)態(tài)鏈接庫(.so)算吩,作為中間適配層橋接,實(shí)現(xiàn)了JS端與原生端的雙向通信交互佃扼。React Native會(huì)把應(yīng)用的JS代碼編譯成一個(gè)JS文件偎巢,React Native整體框架目標(biāo)就是為了解釋并運(yùn)行這個(gè)JS腳本文件,如果是JS擴(kuò)展的API兼耀,則直接通過bridge調(diào)用native压昼;如果是UI界面求冷,則映射到virtual DOM這個(gè)虛擬的JS數(shù)據(jù)結(jié)構(gòu)中,通過bridge傳遞到native窍霞,然后根據(jù)數(shù)據(jù)設(shè)置各個(gè)對應(yīng)的真實(shí)native的View匠题。
weex
Weex是阿里巴巴于2016年發(fā)布的跨平臺(tái)移動(dòng)端開發(fā)框架,思想及原理和React Native類似但金,最大的不同是語法層面韭山,Weex支持Vue語法和Rax語法,Rax 的 DSL 語法是基于 React JSX 語法而創(chuàng)造冷溃。與 React 不同钱磅,在 Rax 中 JSX 是必選的,它不支持通過其它方式創(chuàng)建組件似枕,所以學(xué)習(xí) JSX 是使用 Rax 的必要基礎(chǔ)盖淡。而React Native只支持JSX語法。
在最上面的DSL菠净,阿里一般稱之為Weex文件(.we)禁舷,通過Transform轉(zhuǎn)換為js-bundle,再部署到服務(wù)器毅往,這樣服務(wù)端就完成了。在客戶端派近,第一層是JS-Framework攀唯,最后是RenderRengine。
Weex的輸入是Virtual DOM渴丸,輸出是native或H5 view侯嘀,還原為內(nèi)存中的樹型數(shù)據(jù)結(jié)構(gòu),再創(chuàng)建view谱轨,作為一套前端跨平臺(tái)技術(shù)框架戒幔,WEEX建立了一套源碼轉(zhuǎn)換以及原生平臺(tái)與JavaScript通信的機(jī)制。WEEX表面上是一個(gè)客戶端框架土童,但實(shí)際上它串聯(lián)起了從本地開發(fā)诗茎、云端部署到分發(fā)的整個(gè)鏈路。
這兩種方法都有各自的生態(tài)献汗,相比weiview方式性能體驗(yàn)要大大提升敢订,然而在高度要求動(dòng)畫效率及游戲方面的應(yīng)用還是顯得有點(diǎn)不夠用。
自繪UI+原生
目前采用這種方式的就是Flutter了罢吃。和上兩種不同的是楚午,這種方式采用了自己的渲染引擎,所有UI都由自己繪制并渲染尿招,少了中間層的轉(zhuǎn)化矾柜,性能的高效就顯而易見了阱驾。
Flutter
Flutter是Google推出并開源的移動(dòng)應(yīng)用開發(fā)框架,主打跨平臺(tái)怪蔑、高保真里覆、高性能。開發(fā)者可以通過Dart語言進(jìn)行APP開發(fā)饮睬,只需要一套代碼就可以同時(shí)構(gòu)建Android和iOS應(yīng)用租谈,并且可以達(dá)到與原生應(yīng)用一樣的性能。Flutter還提供了豐富的組件捆愁、接口割去,開發(fā)者可以高效地為 Flutter添加native擴(kuò)展。此外昼丑,F(xiàn)lutter還使用Skia作為2D引擎渲染呻逆,Skia是Google的一個(gè)2D圖形處理函數(shù)庫,在字型菩帝、坐標(biāo)轉(zhuǎn)換以及點(diǎn)陣圖等方面都有高效而且簡潔的表現(xiàn)咖城。Skia是跨平臺(tái)的,并提供了非常友好的API呼奢。由于Android系統(tǒng)已經(jīng)內(nèi)置了Skia宜雀,所以Flutter在打包APK時(shí),不需要再將Skia打包到APK中握础,但是iOS系統(tǒng)并未內(nèi)置Skia辐董,所以在構(gòu)建API時(shí),必須將Skia一起打包禀综。
Flutter的高性能保障
目前简烘,F(xiàn)lutter程序主要有兩種運(yùn)行方式:靜態(tài)編譯與動(dòng)態(tài)解釋。靜態(tài)編譯的程序在執(zhí)行前定枷,會(huì)被全部翻譯為機(jī)器碼孤澎,通常將這種類型稱為AOT,即 “提前編譯”欠窒。解釋執(zhí)行則是一句句地邊翻譯邊運(yùn)行覆旭,通常將這種類型稱為JIT,即“即時(shí)編譯”贱迟。 AOT程序的典型代表是用C/C++開發(fā)的應(yīng)用姐扮,它們必須在執(zhí)行前編譯成機(jī)器碼。而JIT的代表則非常多衣吠,如JavaScript茶敏、python等。事實(shí)上缚俏,所有腳本語言都支持JIT模式惊搏。但需要注意的是贮乳,JIT和AOT指的是程序運(yùn)行方式,和編程語言并非是強(qiáng)關(guān)聯(lián)的恬惯,有些語言既可以以JIT方式運(yùn)行向拆,也可以以AOT方式運(yùn)行,如Java酪耳、Python浓恳,它們可以在第一次執(zhí)行時(shí)編譯成中間字節(jié)碼,然后在之后的執(zhí)行中碗暗,直接執(zhí)行字節(jié)碼颈将。
Flutter的高性能主要靠兩點(diǎn)來保證,首先言疗,F(xiàn)lutter APP采用Dart語言進(jìn)行開發(fā)晴圾。當(dāng)Dart在 JIT模式下時(shí),其運(yùn)行速度與 JavaScript基本持平噪奄。此外Dart支持 還AOT死姚,當(dāng)Dart在 AOT模式下事,其運(yùn)行速度遠(yuǎn)超JavaScript勤篮。速度的提升對高幀率下的視圖數(shù)據(jù)計(jì)算很有幫助都毒。 其次,F(xiàn)lutter使用自己的渲染引擎來繪制UI碰缔,布局?jǐn)?shù)據(jù)等由Dart語言直接控制温鸽,所以在布局過程中不需要像RN那樣要在JavaScript和Native之間通信,在一些滑動(dòng)和拖動(dòng)的場景下具有明顯優(yōu)勢手负。由于滑動(dòng)和拖動(dòng)往往會(huì)引起布局的變化,所以JavaScript需要不停地與Native之間同步布局信息姑尺,這和在瀏覽器中要JavaScript頻繁操作DOM所帶來的問題是相同的竟终,都會(huì)帶來比較可觀的性能開銷。因此切蟋,F(xiàn)lutter能保證每端運(yùn)行的UI都維持高度一致统捶。