Flutter初探:基本觀念筆記
(還有待整理跟補充)
Flutter框架結構
- 框架層Framework(Dart):
why Dart(開發時JIT即時編譯/發布時AOT提前編譯)
- Material/Cupertino
- Widgets
- Rendering
- Animation/Painting/Gestures
- 引擎層Engine(C/C++)
- 嵌入層Platform-specific
Flutter環境設置
- install flutter and revise bash path for flutter
- code . ~/.bash_profile 編輯檔案新增下面那行指定路徑
- export PATH="$PATH:/Users/florachen/flutter/bin"
- echo $PATH 或是 which flutter 檢查路徑對不對
- flutter doctor檢查開發環境
- shift command P 創建 => Flutter:New Project
- flutter run (要開模擬器即時更改要切debug模式)
- Xcode(IOS simulator)
- sudo gem install xcode-install
- 輸入xcversion會跳出apple認證如果認證失效可以輸入( rm $HOME/.fastlane/spaceship/*/cookie )
- xcversion list 列出所有版本以及已有安裝的版本
- xcversion install 13.4.1
- xcversion installed
- xcrun –version(確認有沒有安裝Xcode command line tool)
- xcrun simctl list(列出所有可用的機型id)
- xcrun simctl boot 5EE6154A-A997-46AF-811C-A95918878C43(在vscode中選取ios simulator)
- xcrun simctl shutdown [device id]
- VScode 安裝 flutter & dart
- android studio
- brew install –cask android-studio
- firebase
- curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
- nvm alias default {{ 預設版本號 }} nvm list nvm use {{ 版本號 }} 切換當前命令列所使用的 Node.js 版本
- npm install -g firebase-tools (firebase需要nodejs14)
- firebase login
- flutterfire configure連結現有data or 創建
- initialize firebase 必須在一開始
- 若設置使用者可以用信箱跟密碼登入 必須在註冊後收驗證信再讓使用者登入才能取得已驗證的userCredential
Dart
- variable:可更改(var)但型別不能改
- const 不可
- final:不可更改的var//可以省略類型聲明
final str = "hi world";=>final String str = "hi world";
*late 現在還沒但之後會有的變數(?
dynamic dynamic是所有物件的基礎類型,也就是說它可以代表任何物件。
- 空安全(null-safety)
=>fun?.call() //fun 不为空时则会被调用
- dynamic和Object: dynamic與Object聲明的變量都可以賦值任意對象,且後期可以改變賦值的類型
- 函數
- 集合
- Lists(同義於array) 可在定義時帶入型別或是長度,常見的方法:reversed/contains/map/forEach/…
Collection if & Collection for
- 如果要不能修改可以使用UnmodifiableListView(users)
- Sets
- Sets 是沒有索引值、!不可重複!的集合,以hashCode的值來決定是否相等。
- var sets = <int>{1,2,3,4};//如果初始化未給定型別 dart會自動判斷
- 範例:
- Maps
+ putIfAbsent():當該key(height)無值時插入值170 /或是直接info['height']=180/remove(Object):
ex:info.putIfAbsent('height',()=>170)
+ update(key, value) containsKey(key) containsValue(value)
8. enum 是一種型別,用於自定義 type,若用在 switch 上,IDE 會自動告訴我們有哪一個 enum 尚未考慮到。
9. 宣告class時預設都是public 可加(_)變private,
10. 使用operator來處理等價與否,
- StatelessWidget:是一個不需要自己紀錄內部狀態的組件,需要的資料只能靠外部提供。
(stl or stf vscode打了就會自動生成)
- StatefulWidget:是有自己內部狀態的組件,可以建立自己的state也可以接受外部的prop,一個StatefulWidget會分開定義「widget」和「widget所使用的狀態」。
- WHY???由於Flutter 的widget創建後內部的資料是不能更動(immutable)的,要更改畫面必須重新創建,因此採用「創建widget」之後「注入state」方法,由state來掌管可變的狀態。
此外將state與widget拆分,也可以確保每次widget重製時,state可以獨立於widget之外仍然保留狀態。
- 盡量只讓需要變動的組件採用StatefulWidget,而可以單純依照外部資料顯示的組件採用StatelessWidget,才能最有效地分配運算資源。
佈局約束策略
- xConstraints go down.
Child Widget並不是長寬設為多少就會長成多少,必須接受來自上層的Parent Widget最大長寬度的限制。
- Sizes go up.
各個Child Widget皆會將自身期望的長寬包含約束條件向上傳遞給Parent Widget。
- Parent sets position.
Parent統整了所有Child Widget的尺寸資訊後,便開始在畫面上依照大小決定各自的位置
Layout
-
Single Child Layout Widget
Align:對齊
AspectRatio:指定比例
Center:置中
ConstratinedBox:長寬限制
Container:外框容器
Expanded:盡可能佔據剩餘空間
Padding:與外框的間隙:
- fromLTRB(double left, double top, double right, double bottom):分别指定四个方向的填充。
- all(double value) : 所有方向均使用相同数值的填充。
- only({left, top, right ,bottom }):可以设置具体某个方向的填充(可以同时指定多个方向)。
- symmetric({ vertical, horizontal }):用於對稱方向的填充,vertical指top和bottom,horizontal指left和right。
SingleChildScrollView:加上頁面捲軸
-
Multi Child Layout Widget
Column:垂直排列
GridView:網格式排列
ListView:列表式排列
Row:水平排列
Stack:堆疊排列(後面元素在前)
-
Leaf Widget
Widget樹的葉子節點,用於沒有子節點的widget,通常基礎組件都屬於這一類,如Image。
導頁 - navigation
route stack:進入新的頁面,頁面所在的路徑會依序被加入(push)到route stack,退出時也會從「最後進入的頁面」開始退出(pop),從route stack刪除。
- 返回上一頁
要返回的頁面設置Navigation.pop()
- 指定路徑
routes: {
'/first': (context) => const FirstScreen(),
},
Future
當我們呼叫一個非同步函式時,會回傳一個「未完成的Future」來等待此函式的非同步行為執行完畢,並獲得結果,也可能在執行的過程中出現問題而回傳錯誤(promise感) 一樣會有.then .catchError 最後要做的事=> whenComplete
延遲function (setTimeOut感)
Future.delayed(const Duration(seconds: 2), () => print('Here I come!'));
事件處理
- 原始指針(pointer):鼠標、觸控筆
this.onPointerDown, //手指按下回调
this.onPointerMove, //手指移动回调
this.onPointerUp,//手指抬起回调
this.onPointerCancel,//触摸事件取消回调
- 手勢:拖拉、雙擊等等
GestureDetector是一個用於手勢識別的功能性組件,我們通過它可以來識別各種手勢。
- Provider/Consumer (額外加入 類似redux)
- 設定一個「狀態管理組件」(ChangeNotifierProvider),放在想要傳遞資料以及使用資料的組件(在專案中是指MainPage, FavoritePage)的上層。
- 接著,「狀態管理組件」會創建一筆「可訂閱的資料模型」(extends ChangeNotifier),也就是我們這次指稱的app state,供各組件訂閱使用(Comsumer)或操作(Provider.of)。
- 當資料被修改,ChangeNotifier可以通知訂閱此資料模型的組件,依照最新的資料重繪。
- Consumer:在子組件中取用Provider/ChangeNotifierProvider提供的資料
其他:
print=console.log
command + .==>快速wrap或是unwrap
$變數 如果要印$就要加$
void是沒有return東西的function 有return就會在一開始宣告return的東西的型別
在main()的東西不會hot reload 需要restart
只有雙等號而已