Flutter簡介
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採用GPU渲染技術,Flutter編寫的應用是可以達到120fps(每秒傳輸幀數),這也就是說,它完全可以勝任遊戲的製作,而我們常說的RN的效能只能達到60fps,這也算是Flutter的一個超高競爭力,官方宣稱Flutter甚至會超過原生效能。如果你想邁入移動遊戲領域,學習Flutter也是一個非常好的選擇。
Flutter高效能主要靠兩點來保證:
- 首先,Flutter App採用Dart語言開發,Dart在JIT(即時編譯)模式下,速度與JavaScript基本持平;而且Dart還支援AOT(提前編譯)模式,當以AOT模式執行時,JavaScript便遠遠追不上了。速度的提升對高幀率下的檢視資料計算很有幫助。
- 其次,Flutter使用自己的渲染引擎來繪製UI,佈局資料等由Dart語言直接控制,所以在佈局過程中不需要像RN那樣通過JavaScriptCore在JavaScript和原生之間進行通訊,這在一些滑動和拖動的場景下具有明顯優勢,因為在滑動和拖動過程中往往都會引起佈局發生變化,所以JavaScript需要和原生之間不停的同步佈局資訊,這和在瀏覽器中要JavaScript頻繁操作DOM所帶來的問題是相同的,都會帶來比較可觀的效能開銷。
為什麼Flutter採用Dart語言開發?
這是一個很有意思,同時具有爭議的問題,在瞭解Flutter為什麼選擇了Dart而不是JavaScript之前,我們先來介紹兩個概念:JIT和AOT。
目前,程式主要有兩種執行方式:靜態編譯和動態解釋。
- 靜態編譯:靜態編譯的程式在執行前全部被翻譯為機器碼,通常將這種型別稱為AOT(Ahead of time)即“提前編譯”;
- 動態解釋:動態解釋的程式是在執行中一句一句邊翻譯邊執行的,通常將這種型別稱為JIT(Just-in-time)即“即時編譯”。
AOT程式的典型代表是用C/C++開發的應用,它們必須在執行前編譯成機器碼,而JIT的代表則非常多,如JavaScript、Python等,事實上,所有指令碼語言都支援JIT模式。但值得一提的是JIT和AOT指的是程式執行方式,它們和程式語言並非強關聯,有些語言既可以以JIT方式執行也可以以AOT方式執行,如Java、Python,它們可以在第一次執行時編譯成中間位元組碼,然後在之後執行時可以直接執行位元組碼,也許有人會說,中間位元組碼並非機器碼,在程式執行時仍然需要動態將位元組碼轉為機器碼,是的,不過通常我們區分是否為AOT的標準就是看程式碼在執行之前是否需要編譯,只要需要編譯,無論其編譯產物是位元組碼還是機器碼,都屬於AOT。在此,讀者不必糾結於概念,概念就是為了傳達精神而發明的,只要讀者能夠理解其原理即可,正所謂得其神忘其形。
現在我們看看Flutter為什麼選擇Dart語言?筆者根據官方解釋以及自己對Flutter的理解總結了以下幾條(由於其它跨平臺框架都將JavaScript作為其開發語言,所以主要將Dart和JavaScript做一個對比):
- 開發效率高
- 基於JIT的快速開發週期:Flutter在開發階段採用JIT模式,這樣就避免了每次改動都要進行編譯,極大的節省了開發時間;(Dart執行時支援)
- 基於AOT的釋出包:Flutter在釋出時可以通過AOT生成高效的ARM程式碼以保證應用效能,而JavaScript則不具有這個能力。(編譯器支援)
-
高效能
Flutter旨在提供流暢、高保真的UI體驗。為了實現這一點,Flutter需要能夠在每個動畫幀中執行大量的程式碼,這意味著需要一種既能提供高效能的語言,又不會出現丟幀的週期性暫停,而Dart支援AOT,在這一點上可以做的比JavaScript更好。
-
快速記憶體分配
Flutter框架使用函式式流,這使得它在很大程度上依賴於底層的記憶體分配器。因此,擁有一個能夠有效的處理瑣碎任務的記憶體分配器將顯得十分重要,如果Dart語言缺乏此功能,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的工作負載更為重要。”
Flutter框架結構
下面我們將對Flutter的框架做一個整體介紹,旨在讓讀者心中有一個整體的印象,這對初學者來說非常重要。如果一下子便深入到Flutter中,就會像是一個在沙漠中沒有地圖的人,即使可以找到一個綠洲,但是他也不會知道下一個綠洲在哪兒。因此,無論學什麼技術,都要先有一張清晰的“地圖”,而我們的學習過程就是“按圖索驥”,這樣我們才不會陷於細節而“目無全牛”。接下來,我們看一下Flutter官方提供的一張框架結構圖:
Flutter Framework
這是一個純Dart實現的SDK,它實現了一套基礎庫,自底向上,簡單介紹一下:
- 底下兩層(Foundation層和Animation、Painting、Gestures層)在Google的一些視訊中將這兩層合併為一個Dart UI層,對應的是Flutter中的
dart:ui
包,它是Flutter引擎暴露的底層UI庫,提供動畫、手勢及繪製功能。 - Rendering層,這一層是一個抽象的佈局層,它依賴於Dart UI層,Rendering層會構建一個UI樹,當UI樹有變化時,會計算出有變化的部分,然後更新UI樹,最終將UI樹繪製到螢幕上,這個過程類似於React中的虛擬DOM。Rendering層可以說是Flutter UI框架最核心的部分,它除了確定每個UI元素的位置、大小之外還要進行座標變換、繪製(呼叫底層
dart:ui
包)。 - Widgets層是Flutter提供的一套基礎元件庫,在基礎元件庫之上,Flutter還提供了Material和Cupertino兩種視覺風格的元件庫。而我們Flutter開發的大多數場景,只是和Widgets層和Material、Cupertino層打交道。
Flutter Engine
這是一個純C++實現的SDK,其中包括Skia引擎、Dart執行時和文字排版引擎等。在程式碼呼叫dart:ui
庫時,呼叫最終會走到Engine層,然後實現真正的繪製邏輯。
總結
Flutter框架本身有著良好的分層設計,本章旨在讓讀者對Flutter整體框架有個大概的印象,相信到現在為止,讀者已經對Flutter有一個初始印象,在我們正式動手之前,我們還是需要多瞭解一下Flutter的開發語言Dart。
如何學習Flutter
資源
- 官網:閱讀Flutter官網的資源是快速入門的最佳方式,同時官網也是瞭解最新Flutter發展動態的地方,由於目前Flutter仍然處於快速發展階段,所以建議讀者要時不時的去官網看看有沒有新的動態。
- 原始碼及註釋:原始碼和註釋應作為學習Flutter的第一文件,Flutter SDK的原始碼是開源的,並且註釋非常詳細,也有很多示例,實際上,Flutter官方的SDK文件就是通過註釋生成的。原始碼結合註釋可以幫你解決大多數問題。
- Github:如果遇到的問題在StackOverflow上也沒有找到答案,可以去Github Flutter 專案下提issue。
- Gallery原始碼:Gallery是Flutter官方示例APP,裡面有豐富的示例,讀者可以在網上下載安裝。Gallery的原始碼在Flutter原始碼“examples”目錄下。
社群
- StackOverflow:如果你還沒聽過StackOverflow,那麼我現在就可以告訴你,它是目前全球最大的程式設計師問答社群,也是現在活躍度最高的Flutter問答社群。StackOverflow社群除了世界各地的Flutter使用者會在上面交流之外,Flutter開發團隊的成員也經常會在上面回答問題。
- Flutter中文網社群:Flutter中文網是wendux(牛人)維護的Flutter中文網站,也是目前最大的Flutter中文資源社群,上面提供了Flutter官網的文件翻譯、開源專案及案例,還有申請加入組織的入口哦!筆者的文章很多都是整理於此。
- 掘金:掘金的Flutter主頁目前收集了不少的專業性部落格文章,讀者可以自行瀏覽。
此文章整理於:book.flutterchina.club/