近些年來,不斷的有前端跨平臺方案涌現出來,比如基于WebView的Cordova,還有渲染成原生控制元件的Reactive、Weex等,那么,這些跨平臺方案有什么通用的實作思路呢,而Flutter的設計思路與他們的區別又是什么呢,帶著這些疑問,本章將會介紹什么是跨平臺,常見的跨平臺方案有哪些,以及Flutter的實作方案,
1.1 跨平臺解決方案
1.1.1 什么是跨平臺
我們知道,CPU有不同的架構和指令集,上層也有不同的作業系統,一個系統的可執行檔案在另一個系統上就是不可執行的,比如Windows的exe檔案在Mac上就不能直接執行,這是因為不同平臺提供的API不同,因此需要不同平臺單獨維護代碼,這樣就帶來了幾個問題:
1.開發成本大,各平臺都要獨立開發一套代碼
2.測驗成本大,各平臺都需要單獨測驗
3.維護成本大,各平臺都要獨立迭代維護
因此,大家都在試圖找到一種方案,能夠實作一份代碼運行在任意平臺,這樣就可以大大提升開發、測驗效率,降低維護成本,這種方案就是跨平臺,
1.1.2 各領域跨平臺方案
1 瀏覽器
瀏覽器是一種歷史悠久的跨平臺方案,通過在不同平臺安裝對應平臺的瀏覽器,來屏蔽底層的差異,瀏覽器提供統一的DOM API,這樣上層的網頁開發就可以統一按照W3C標準,實作一套代碼運行在不同平臺的瀏覽器中,由瀏覽器引擎完成頁面渲染,

圖1.1 瀏覽器方案
2 Docker
Docker是一個開源的應用容器引擎,Docker可以讓開發者將他們的開發環境、代碼、組態檔等一并打包到一個輕量級、可移植的容器中,然后發布和應用到任意平臺,Docker是通過通過在作業系統之上加一個虛擬層,在這層劃分一到多個容器,容器里再去跑系統、App,然后動態的將硬體資源分配給容器,這樣可以實作硬體和軟體的分離,

圖1.2 Docker
3 Java
Java實作跨平臺是因為Java虛擬機JVM,我們將不同平臺的虛擬機安裝在不同的作業系統中,開發者只需要將Java原始碼編譯成JVM能執行的位元組碼就可以了,這樣就實作了一套代碼運行在不同的作業系統中,

1.1.3 前端主流跨平臺方案
1 Hybird App
Hybird App的主要原理就是通過H5技術來實作一個網頁,再通過原生的網頁加載控制元件WebView來加載,WebView是一個基于webkit的引擎,可以決議DOM元素,展示HTML頁面的控制元件,他的原理和瀏覽器展示頁面的原理是相同的,實質上就是一個瀏覽器的內核,對于訪問系統檔案、藍牙等,都需要原生開發,然后暴露給WebView供Java呼叫,呼叫的方式稱為WebView Java Bridge,簡稱:JsBridge,

基于WebView的框架有點很明顯,他們幾乎可以完全繼承現代Web開發的所有成果,包括豐富的控制元件庫、滿足各種需求的頁面框架、完全的動態化、自動化測驗工具等等,而且Web開發人員,不需要太多的學習成本就可以開發 一個App,但是WebView框架有一個致命的缺點,那就是WebView的渲染效率和JavaScript執行性能太差,
2 ReactNative
隨著移動設備的普及和使用范圍越來越廣,App的性能已經越來越重要了,為了解決WebView性能差的問題,以ReactNative為代表的一類框架出現了,它將最終渲染作業還給了系統,雖然同樣使用HTML+CSS+JS的UI構建邏輯,但是最侄訓生成對應的原生控制元件,以充分利用原生控制元件較高的繪制效率,

ReactNative中所有的標簽都不是真實控制元件,JS代碼中的DOM布局會被決議成原生平臺的控制元件,如標簽對應ViewGroup/UIView,對應ScrollView/UIScrollView,對應ImageView/UIImageView,最終堆疊出一系列原生控制元件進行渲染,這種策略同時也將框架本身綁在了系統的控制元件上,拋開框架本身需要處理大量平臺相關的邏輯,隨著系統版本和API的變化,開發者也要不斷的處理不同平臺的差異,這種設計思想在后來阿里開源的Weex框架中也有所體現,但是Weex使用了V8引擎和Vue的設計理念,
3 Unity、Qt for mobile
Unity就是大家熟知的3D游戲引擎,Unity和Qt都采用了自繪UI+原生的跨平臺技術,這種技術的思路是通過在不同平臺實作一個統一的渲染引擎介面來繪制UI,而不依賴系統的原生控制元件,這樣就做到了不同平臺UI的一致性,也不會依賴原生控制元件,受原生系統的限制,而且,因為自繪引擎是直接呼叫系統API來繪制UI,所以性能非常好,和原生控制元件接近, Flutter就屬于這一類跨平臺技術,即從頭到尾寫一套跨平臺的UI框架,包括UI控制元件、渲染邏輯甚至開發語言,渲染引擎依靠跨平臺的Skia圖形庫來實作,可以最大程度上保證不同平臺、不同設備的體驗一致性,邏輯處理使用支持AOT的Dart語言,執行效率比JavaScript高的多,
1.1.4 跨平臺通用原理
通過上述跨平臺方案的了解,我們不難發現,其實跨平臺的解決方案都很類似,都是提供一個容器,容器屏蔽底層差異,并向上層提供統一的API,跨平臺分為渲染跨平臺和邏輯跨平臺,Weex、ReactNative的渲染是通過Virtual Dom,生成對應的原生控制元件,再由Android、iOS各自渲染,邏輯部分則使用了JS引擎,執行代碼,
不論具體實作怎樣,思路都大同小異,跨平臺需要實作一個渲染引擎、一個VM虛擬機,再基于這套架構實作各種組件和API,Flutter就是使用了Skia渲染引擎和Dart VM,實作了跨平臺,

圖1.7 跨平臺方案
1.2Flutter簡介
1.2.1 什么是Flutter
Flutter是Google在2015年開源的一套全新的跨平臺UI框架,作為新一代的跨平臺方案,Flutter能幫助開發者通過一套代碼庫高效構建多平臺的精美應用,支持移動、Web、桌面和嵌入式平臺,而且Flutter是未來新作業系統Fuchsia的默認開發軟體,它的優勢主要包括:
-
跨平臺開發,真正做了一套代碼可以同時在Android和iOS等平臺上運行,避免了過高的維護成本,提高了開發效率,
-
性能優越,通過“自繪UI+原生系統”實作高幀率的流暢UI,性能媲美原生,渲染引擎依靠跨平臺的Skia圖形庫來實作,直接呼叫系統的圖形繪制相關介面,可以在最大程度上保證不同平臺、不同設備的體驗一致性,邏輯處理使用了支持AOT的Dart語言,同時執行效率也比JavaScript高得多,
-
熱多載快速開發,Flutter選用了Google于2011年推出的Dart作為其開發語言,Dart既支持是AOT(Ahead Of Time)編譯,也支持是JIT(Just In Time)編譯,AOT指運行前編譯,JIT是即時編譯,邊運行邊編譯,兩種編譯方式的主要區別在于是否在運行時進行編譯,AOT保證了運行期間頁面加載的高性能,JIT保證了Flutter在開發階段可以達到亞秒級熱多載,而且不會丟失狀態,從而大大提升了開發效率,
1.2.2 Flutter的優缺點
現在,我們來對前端跨平臺方案做一個對比,大家可以結合自身的業務情況選擇合適的跨平臺方案: 跨平臺方案:
| 方案 | 原生 | Web容器 | React Native | Flutter |
|---|---|---|---|---|
| 靜態性能 | 好 | 差 | 適中 | 好 |
| 滾動性能 | 好 | 差 | 適中 | 好 |
| 區塊級支持 | 好 | 差 | 一般 | 一般 |
| 適用場景 | 對性能和穩定性要求極高,希望提供在各平臺上互動和體驗極致的核心功能和頁面 | 對性能要求不高,重展示弱互動,更關注迭代和交付效率的頁面 | 希望能平衡性能、展示互動能力和迭代交付效率,對包大小敏感的頁面 | 對性能、穩定性和多端體驗一致性要求高、對動態化及包大小無特殊要求,更關注提升原生迭代效率的中等核心頁面 |
| 跨平臺 | 差 | 好 | 好 | 好 |
| 開發效率 | 差 | 好 | 好 | 好 |
| 體驗一致性 | 差 | 好 | 一般 | 好 |
| 頁面級支持 | 很高 | 好 | 好 | 好 |
| 動態化支持 | 差 | 好 | 好 | 差 |
| 布局能力 | 好 | 好 | 一般 | 好 |
| 生態 | 好 | 好 | 好 | 好 |
| 維護成本 | 好 | 好 | 適中 | 好 |
| 包大小 | 好 | 好 | 好 | 差 |
| App Store政策風險 | 好 | 好 | 好 | 好 |
| 獨立App開發支持 | 好 | 一般 | 好 | 好 |
1.3Flutter架構設計
接下來,我們來了解一下Flutter的架構設計,Flutter架構是非常清晰的,總共分為三層:
-
框架層(Framework):Flutter框架層是純Dart語言實作的一個回應式框架,開發者平常需要通過該層和Flutter系統進行互動,
-
引擎層(Engine):引擎層提供了一系列Flutter核心API的底層實作,例如圖形(通過Skia),文字布局,檔案等,是連接框架和系統(Andoird/iOS)的橋梁,引擎層絕大部分是用C++實作的,其為Flutter系統的核心,
-
嵌入層(Embedder):嵌入層為Flutter提供了一個入口,通過該入口訪問底層系統提供的服務,例如輸入法、繪制Surface等,嵌入層基本是由平臺對應的語言實作的,例如在Android上是由Java和C++實作,在iOS上是由Objective-C實作,

1.3.1 Framework框架
Flutter框架最頂層是我們經常用到的Framework框架層,整個框架層都是由Dart語言實作,該層提供一套基礎庫,用于處理影片、繪圖和手勢等,并且封裝了一套UI組件庫Widgets,在基礎組件庫上,Flutter還提供了Material和Cupertino兩種視覺風格的組件庫,通常情況下,你會發現你僅僅使用這兩層中的Widgets就夠用了,并且目前你所能看到或者使用的,也基本都來自這兩層,比如頁面腳手架組件Scaffold和FloatingActionButton來自Meterial層,Column和GestureDetector來自Widgets層,
Widgets層給我們提供了可以直接使用的UI組件,主要分為三類:
-
布局相關(layout):比如Column和Row,這兩個Widget可以幫我們實作水平或者垂直排列組件,
-
繪制相關(Parning):比如Text和Image,這類的組件可以幫我們展示或者渲染一些內容到螢屏上,
-
手勢檢測相關:比如GestureDetector組件,這個組件能夠檢測到螢屏點擊或者滑動事件,
在Widgets層下面是Rendering層,Rendering層簡化了布局和繪制程序,在運行時Rendering層會構建一個Widget樹,當頁面發生變化時,會根據一定的演算法計算出有變化的部分,然后更新Widget樹,
dart:ui是Framework框架的最底層,它負責處理與Flutter Engine的通信,Flutter框架基于這一層來構建應用程式,比如輸入驅動、繪制文字、布局和渲染系統等,所以我們可以僅僅使用dart:ui庫中的類(例如Canvas、Paint和TextField)來構建一個Flutter App,但是這種方法需要精確的計算出你布局中所有元素的坐標,需要繪制到螢屏,同時對外界的輸入時間能夠捕獲并作出回應,
1.3.2 Engine引擎層
Flutter Engine層是純C++實作的,其中包括了Skia引擎、Dart運行時、文字排版引擎等,
-
渲染引擎Skia:Skia(全稱Skia Graphics Library(SGL))是一個由C++撰寫的二維開源圖形庫,Skia就是Flutter向GPU提供資料的途徑,谷歌Chrome瀏覽器、Chrome OS、安卓、火狐瀏覽器、火狐作業系統以及其它許多產品都使用它作為圖形引擎,底層渲染能力統一了,上層開發介面和功能體驗也就隨即統一了,因此,Skia保證了同一套代碼呼叫在Android和iOS平臺上的渲染效果是完全一致的,
-
Dart:主要包括:Dart Runtime,Garbage Collection(GC),如果是Debug模式的話,還包括JIT(Just In Time)支持,Release和Profile模式下,是AOT(Ahead Of Time)編譯成了原生的arm代碼,并不存在JIT部分,
-
Text:即文本渲染,其渲染層次如下:衍生自Minikin的libtxt庫(用于字體選擇,分隔行);HartBuzz用于字形選擇和成型;Skia作為渲染/GPU后端,在Android和Fuchsia上使用FreeType渲染,在iOS上使用CoreGraphics來渲染字體,
1.3.3 Embedding嵌入層
Embedding嵌入層是用于呈現所有Flutter內容的原生系統應用,充當著宿主作業系統和Flutter之間粘合劑的角色,當啟動一個Flutter應用時,嵌入層會提供一個入口,初始化Flutter引擎,獲取UI和柵格化執行緒,創建Flutter可以寫入的紋理,嵌入層同時負責管理應用的生命周期、輸入操作、視窗的大小變化、執行緒管理和平臺訊息的傳遞,Flutter擁有Android、iOS、Windows、macOS和Linux的平臺嵌入層,每一個平臺都有各自的一套API,
-
在iOS和macOS上,Flutter分別通過UIViewController和NSViewController載入嵌入層,嵌入層會創建一個FlutterEngine,作為Dart VM和Flutter運行時的宿主,還有一個FlutterViewController,關聯對應的FlutterEngine,傳遞UIKit或者Cocoa的輸入事件到 Flutter,并將FlutterEngine渲染的幀內容通過Metal或OpenGL進行展示,
-
在Android上,Flutter默認通過一個Activity加載嵌入層,此時Flutter視圖是一個FlutterView,以視圖模式或紋理模式呈現Flutter的內容,
-
在Windows上,Flutter的宿主是一個傳統的Win32應用,內容通過ANGLE進行渲染,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/413870.html
標籤:其他
