本文對應github地址Flutter2,如果由於github調整導致資源找不到,請訪問github
為什麼Flutter選擇了Dart語言(不用js)
- Dart 的效能更好。JIT模式速度與JavaScript持平,AOT模式效能好於JavaScript。
- 縮短開發週期。Debug時預設JIT,且支援熱過載。
- Native Binding。JavaScript在Android上Native Binding可以很好地實現,但iOS上的 JavaScriptCore不可以,Dart的 Native Binding可以很好地通過 Dart Lib實現。
- Fuchsia OS。Fuchsia OS內建的應用瀏覽器就是使用 Dart語言作為 App的開發語言。而且實際上,Flutter是 Fuchisa OS的應用框架概念上的一個子集。(Flutter原始碼和編譯工具鏈也充斥了大量的 Fuchsia巨集)
- Dart是型別安全的語言,擁有完善的包管理和諸多特性。Google召集了如此多個程式語言界的設計專家開發出這樣一門語言,旨在取代 JavaScript,所以 Fuchsia OS內建了 Dart。Dart可以作為 embedded lib嵌入應用,而不用只能隨著系統升級才能獲得更新,這也是優勢之一。
Skia是什麼
- Skia是一個 2D的繪圖引擎庫,其前身是一個向量繪圖軟體,Chrome和 Android均採用 Skia作為繪圖引擎。
- Skia提供了非常友好的 API,並且在圖形轉換、文字渲染、點陣圖渲染方面都提供了友好、高效的表現。
- Skia是跨平臺的,所以可以被嵌入到 Flutter的 iOS SDK中,而不用去研究 iOS閉源的 Core Graphics / Core Animation。
- Android自帶了 Skia,所以 Flutter Android SDK要比 iOS SDK小很多。
Flutter Framework
- 這是一個純 Dart實現的 SDK,類似於 React在 JavaScript中的作用,它實現了一套基礎庫, 用於處理動畫、繪圖和手勢。
- 其繪圖封裝了一套 UI庫(dart:ui),有 Material 和Cupertino兩種視覺風格。我們在使用 Flutter寫 App的時候,直接匯入這個庫即可使用元件等功能
Flutter Engine
- 這是一個純 C++實現的 SDK,其中囊括了 Skia引擎、Dart執行時、文字排版引擎等.
- 它可以以 JIT 或 AOT的模式執行 Dart程式碼。
- 在程式碼呼叫 dart:ui庫時,提供 dart:ui庫中 Native Binding 實現。
- 他還控制著 VSync訊號的傳遞、GPU資料的填充等,並且還負責把客戶端的事件傳遞到執行時中的程式碼
Flutter命名規範
- 檔名: 小寫+下劃線
- 型別名(類名、函式型別名):大寫開頭駝峰
- 變數名(包含const final 常量):使用小寫開頭駝峰
- const可以使用大寫+下劃線的方式
- 方法名:使用小寫開頭駝峰
- 導包as後的名稱為小寫+下劃線
- 不要用匈牙利命名法中的kXXXX 這樣的命名方式,應該去掉k
- 超過兩位的英文縮寫一律按該單詞為普通小寫單詞處理,使用小寫
一些關鍵字
- extends(繼承關鍵字)
- Flutter中的繼承是單繼承
- 建構函式不能繼承
- 子類重寫超類的方法,要用@override
- 子類呼叫超類的方法,要用super
- Scaffold(實現了基本的 Material Design 佈局結構)
- appBar: 介面頂部導航條
- body: 當前介面所顯示的主要內容 Widget
- floatingActionButton: Material設計中定義的一個功能按鈕
- persistentFooterButtons: 固定在下方顯示的按鈕,如對話方塊下方的確定、取消按鈕
- drawer: 抽屜選單控制元件
- backgroundColor: 背景色,預設是 ThemeData.scaffoldBackgroundColor 的值
- bottomNavigationBar: 顯示在頁面底部的導航欄
- resizeToAvoidBottomPadding: 預設true,控制body是否重新佈局來避免底部被覆蓋了,如當鍵盤顯示的時候,重新佈局避免被鍵盤蓋住內容
package匯入要求
- 導包最好按如下順序排序(可以空行分隔)
- dart sdk內的庫
- flutter內的庫
- 第三方庫
- 自己的庫
- 相對路徑引用
一些語法特性
-
=> expr 等同於{ return expr; } 如果無返回值省略return
// forEach list4.forEach((itemValue) => print(itemValue)); list4.forEach((itemValue) { print(itemValue); }); 複製程式碼
-
.. 級聯符號 在同一物件上進行一系列操作
class StarInfo { String name; printInfo() { print("${name}"); } } // 常規 var starInfo1 = StarInfo(); starInfo1.name = "Li Xiaolong"; starInfo1.printInfo(); // 級聯 var starInfo2 = StarInfo(); starInfo2 ..name = "Li XiaoLong" ..printInfo(); // 結尾才有分號 複製程式碼
-
Dart 的類不支援public、private這樣限制詞。_下劃線代表私有。
class TestGetSet { // 私有 String _userName; String _nickName; String get userName { return _userName ?? _nickName; } set userName(String newName) { _userName = newName; } set nickName(String newName) { _nickName = newName; } } // 使用 var testGetSet = new TestGetSet(); testGetSet.nickName = "LiXiaolong"; print("${testGetSet.userName}"); // LiXiaolong 複製程式碼
-
運算子(操作符)
-
算數運算子(加、減、乘、除、商、餘、自加、自減)
print(20 + 2); // 22 加 print(20 - 2); // 18 減 print(20 * 2); // 40 乘 print(20 / 2); // 10 除 print(40 ~/ 3); // 13 商 print(40 % 3); // 1 餘 // i++ int i = 3; var a = i++; // 賦值後i才自加,故a=3 print('a=$a,i=$i'); // a=3,i=4 // ++i int i = 3; var a = ++i; // 執行賦值前i已經自加,故a=4 print('a=$a,i=$i'); // a=4,i=4 // i-- int i = 3; var a = i--; // 執行賦值後i才自減,故a=3 print('a=$a,i=$i'); // a=3,i=2 --i int i = 3; var a = --i; // 執行賦值前i已經自減,故a=2 print('a=$a,i=$i'); // a=2,i=2 複製程式碼
-
關係運算子(大於、小於、等於、不等於、大於等於、小於等於)
print(10 > 20); // false 大於 print(10 < 20); // true 小於 print(10 == 20); // false 等於 print(10 != 20); // true 不等 print(10 >= 3); // true 大於等於 print(10 <= 3); // false 小於等於 複製程式碼
-
位運算子(位與、位或、位非、異或、左移、右移)
// 位與:& 兩個都是1為1 // 位或:| 只要有1就是1 // 位非:~ 全取反 // 異或:^ 位都不一樣為1 // 左移:<< 整體左移,不足補0 // 右移:>> 整體右移 複製程式碼
-
邏輯運算子(邏輯與、邏輯或、邏輯非)
bool isGreen = true; bool isBlack = false; print("${isGreen && isBlack}"); // false 邏輯與 print("${isGreen || isBlack}"); // true 邏輯或 print("${!isBlack}"); // true 邏輯非 複製程式碼
-
賦值運算子
= ?? // AA ?? "99" 表示如果 AA 為空,返回99 ??= // AA ??= "99"如果 AA 為空,給 AA 設定成 99 += -= *= /= ~/= %= <<= =>> &= |= ^= 複製程式碼
-
條件表示式
expr1 ? expr2 : expr3 // 三目運算子 如果 if(expr1) expr2 else expr3 expr1 ?? expr2 // expr1 ? expr1 : expr2 複製程式碼
-
型別測試操作符
as : 型別轉換
is : 當物件是相應型別時返回 true
is! : 當物件不是相應型別時返回 true
JIT 和 AOT
- JIT(Just In Time):即時編譯,在程式執行中將熱點程式碼編譯成機器碼,以提升開發效率。JIT可以充分利用解釋型語言的優點,動態執行原始碼,而不用考慮平臺差異性,JIT模式需要配合DartVM使用。
- AOT(Ahead Of Time):執行前編譯,在程式執行之前,已經編譯成對應平臺的機器碼,不需要在執行中解釋編譯就可以直接執行,AOT需要使用runtime來執行。
- 四種編譯模式
- Script:最常見的JIT模式,可以直接在虛擬機器中執行Dart原始碼,像解釋型語言一樣使用。通過
Dart xxx.dart
直接執行,適合寫一些臨時指令碼。 - Kernel Snapshots:也是JIT模式,又稱為Script Snapshots,和Script不同的是,這種模式執行的是Kernel AST的二進位制資料,這裡不包含解析後的類和函式以及編譯後的程式碼,所以不能在不同平臺之間移植。 Dart Kernel是Dart程式中一種中間語言,可通過
dart --snapshot-kind=kernel --snapshot=xxx.snapshot xxx.dart
生成 - JIT Application Snapshots:也是JIT模式,執行的是解析過的類和函式以及編譯後的程式碼,所以執行更快,但只能針對32位或64位架構執行,可通過
dart --snapshot-kind=app-jit --snapshot=xxx.snapshot xxx.dart
生成 - AOT Application Snapshots:AOT模式,原始碼被提前編譯成特定平臺的二進位制檔案。要用AOT模式,需要
dart2aot
命令,如dart2aot xxx.dart xxx.dart.aot
然後用dartaotruntime
命令執行
斷言 assert
- assert(條件) 如果條件不滿足,會中斷程式的執行,否則繼續執行
參考文章