為什么那么多公司鐘愛(ài) Flutter ?
1. 背景與問(wèn)題
中小公司維護(hù)一個(gè) App 的成本好高呀,有沒(méi)有辦法可以降低成本的可能性,但是又不想讓代碼缺少維護(hù)?
有沒(méi)有方案可以實(shí)現(xiàn)一份代碼可以運(yùn)行在多個(gè)平臺(tái),減少溝通成本呢?
2. 問(wèn)題方案選擇
各公司都開(kāi)始關(guān)注和使用跨端方案【包括大廠阿里巴巴以及騰訊】目前主流的跨端方案主要分為兩種:一種是將 JavaScriptCore 引擎作為虛擬機(jī)的方案,代表框架是 React Native;另一種是使用非 JavaScriptCore 虛擬機(jī)的方案,代表框架是 Flutter。【其中還有一種是使用 Webview 的方案-待會(huì)也會(huì)講解到】
使用跨端方案進(jìn)行開(kāi)發(fā),必然會(huì)替代原有平臺(tái)的開(kāi)發(fā)技術(shù),所以我們?cè)谶x擇跨端方案時(shí),不能只依賴于某幾項(xiàng)指標(biāo),比如編程語(yǔ)言、性能、技術(shù)架構(gòu)等,來(lái)判斷是否適合自己團(tuán)隊(duì)和產(chǎn)品,更多的還要考慮開(kāi)發(fā)效率、社區(qū)支持、構(gòu)建發(fā)布、 DevOps、 CI 支持等工程化方面的指標(biāo)。

目前本公司其它項(xiàng)目采用的是 Flutter 和 Swift 混編,感覺(jué)下一步本負(fù)責(zé)項(xiàng)目也要進(jìn)入這個(gè)模式,所以開(kāi)啟 Flutter 之旅。
希望通過(guò)本篇博客,大家能夠理解為什么選擇 Flutter,以及幾種跨平臺(tái)的區(qū)別,歡迎關(guān)注與點(diǎn)贊,彼此共同進(jìn)步,謝謝!??!
3. 方案特點(diǎn)原理

? 3.1 方案一 Webview
Webview 是基于 JavaScript 和 WebView 的跨平臺(tái)。主要工作在 Webkit 中完成
最早出現(xiàn)的跨平臺(tái)框架是基于 JavaScript 和 WebView,代表框架有 PhoneGap,Apache Cordova,Ionic 等。
WebView 主要是通過(guò) HTML 來(lái)構(gòu)建自己的界面,再將其顯示在各個(gè)平臺(tái)的 WebView中,但是它默認(rèn)是不能調(diào)用本地的一些服務(wù)的【比如藍(lán)牙、相機(jī)等】所以需要調(diào)用JavaScript 進(jìn)行橋接調(diào)用 Native 的一些代碼來(lái)完成某些功能。但是根據(jù)本人親自對(duì)WebView 的使用,WebView 的性能并不夠理想,而且開(kāi)發(fā)過(guò)程中的坑也比較多。
下圖是 WebView 的原理圖 -- 認(rèn)真看下

? 3.2 方案二 React Native
React Native【簡(jiǎn)稱RN】是 Facebook 于2015年4月開(kāi)源的跨平臺(tái)移動(dòng)應(yīng)用開(kāi)發(fā)框架,,是 Facebook 早先開(kāi)源的 JS 框架 React 在原生移動(dòng)應(yīng)用平臺(tái)的衍生產(chǎn)物,目前支持 iOS 和安卓?jī)纱笃脚_(tái)。
RN 使用 JavaScript 語(yǔ)言類似于 HTML 的 JSX,以及 CSS 來(lái)開(kāi)發(fā)移動(dòng)應(yīng)用,并且在保留基本渲染能力的基礎(chǔ)上,用原生自帶的UI組件實(shí)現(xiàn)核心的渲染引擎,從而保證了良好的渲染性能。
但是,由于 RN 的本質(zhì)是通過(guò) JavaScript VM 調(diào)用原生接口,通信相對(duì)比較低效,而且是間接通過(guò)原生進(jìn)行渲染的。

? 3.3 方法三 Flutter
Flutter 是谷歌的移動(dòng) UI 框架,可以快速在 iOS 和 Android 上構(gòu)建高質(zhì)量的原生用戶界面。Flutter 可以與現(xiàn)有的代碼一起工作。在全世界,F(xiàn)lutter 正在被越來(lái)越多的開(kāi)發(fā)者和組織使用,并且 Flutter 是完全免費(fèi)、開(kāi)源的。
總體來(lái)說(shuō),相比于 React Native 框架,F(xiàn)lutter 的優(yōu)勢(shì)最主要體驗(yàn)在性能、開(kāi)發(fā)效率和體驗(yàn)兩大方面。
React Native 所使用的 JavaScriptCore,原本用在瀏覽器中,用于解釋執(zhí)行網(wǎng)頁(yè)中的JavaScript 代碼。為了兼容 Web 標(biāo)準(zhǔn)留下來(lái)的歷史包袱,無(wú)法專門針對(duì)移動(dòng)端進(jìn)行性能優(yōu)化。Flutter 卻不一樣,它一開(kāi)始就拋棄了歷史包袱,使用全新的 Dart 語(yǔ)言編寫,同時(shí)支持 AOT 和 JIT 兩種編譯方式,而沒(méi)有采用 HTML/CSS/JavaScript 組合方式開(kāi)發(fā),在執(zhí)行效率上明顯高于 JavaScriptCore。
除了編程語(yǔ)言的虛擬機(jī),F(xiàn)lutter 的優(yōu)勢(shì)還體現(xiàn)于UI框架的實(shí)現(xiàn)上。它重寫了 UI 框架,從 UI 控件到渲染,全部重寫實(shí)現(xiàn)了,依賴 Skia 圖形庫(kù)和系統(tǒng)圖形繪制相關(guān)的接口,保證了不同平臺(tái)上能有相同的體驗(yàn)。
Flutter 利用 Skia 繪圖引擎,直接通過(guò) CPU、GPU 進(jìn)行繪制,不需要依賴任何原生的控件?!続ndriod 操作系統(tǒng)中,編寫的原生控件中實(shí)際上也是依賴于 Skia 進(jìn)行繪制,所以 Flutter 在某些 Andriod 操作系統(tǒng)上甚至還要高于原生-因?yàn)樵?Andriod 中的 Skia 必須隨著操作系統(tǒng)進(jìn)行更新,而 Flutter SDK 中總是保持最新的】
? 3.4 Flutter 對(duì)比優(yōu)勢(shì)
下面用 Andriod 平臺(tái)來(lái)對(duì)比:Flutter、原生與 RN 等平臺(tái)的對(duì)比,可以看出除了原生開(kāi)發(fā),F(xiàn)lutter 的性能更高

4. Flutter 剖析
? 4.1 Flutter繪制原理圖
GPU 將信號(hào)同步到 UI 線程
UI 線程用 Dart 來(lái)構(gòu)建圖層樹(shù)
圖層樹(shù)在 GPU 線程中合成
合成后的視圖數(shù)據(jù)提供給 SKia 引擎
Skia 引擎通過(guò) OpenGL 或者 Vulkan 將顯示內(nèi)容提供給 GPU,所以有兩個(gè) GPU 構(gòu)成一個(gè)閉環(huán)
Flutter 和 React Native 的本質(zhì)區(qū)別:
React Native 只能通過(guò) JavaScript 虛擬機(jī)擴(kuò)展調(diào)用系統(tǒng)組件,由 iOS 和 Andriod系統(tǒng)組件的渲染
Flutter 是自己完成了組件渲染的閉環(huán)
微信搜索公眾號(hào) 逆鋒起筆,關(guān)注后回復(fù) 編程資源,領(lǐng)取各種經(jīng)典學(xué)習(xí)資料。
? 4.2 幀率與刷新率
1、基礎(chǔ)知識(shí)
幀率【fps】:Frame Per Second
刷新率:顯示器的頻率,比如 iPhone 的 60HZ 等
拓展:
我們?yōu)槭裁茨芸吹筋愃朴趧?dòng)畫的效果呢?1、這是因?yàn)樗シ诺乃俣确浅??,研究表明:p 當(dāng)圖片連續(xù)播放的頻率超過(guò)16幀(16張圖片),人眼就會(huì)感覺(jué)非常流暢,當(dāng)少于16幀時(shí),會(huì)感覺(jué)到卡頓2、所以我們平時(shí)看到的電影,通常都是24幀或者30幀的(李安之前拍攝120幀的電影,目的就是讓圖片間隔更小,畫面更加的流暢)

? 4.3 雙重緩存【Double Buffer】

-
在某個(gè)時(shí)間點(diǎn),一個(gè)屏幕刷新周期完成,VSync 信號(hào)產(chǎn)生,先完成復(fù)制操作,然后通知 CPU/GPU 繪制下一幀圖像。 -
復(fù)制操作完成后屏幕開(kāi)始下一個(gè)刷新周期,即將剛復(fù)制到 Frame Buffer 的數(shù)據(jù)顯示到屏幕上。 -
在這種模型下,只有當(dāng) VSync 信號(hào)產(chǎn)生時(shí),CPU/GPU 才會(huì)開(kāi)始繪制。

? 4.4 渲染引擎 Skia
推薦閱讀
Flutter 是移動(dòng)應(yīng)用程序開(kāi)發(fā)的未來(lái)?
下載!閑魚(yú)最新升級(jí)版 Flutter 技術(shù)電子書(shū)!
支持下 ![]()
