目錄
- 1. 什么是Widget?Flutter中的Widget分為哪幾類?
- 2. StatelessWidget和StatefulWidget的區別
- 3. StatefulWidget生命周期
- 4. 什么是BuildContext?
- 5. 如何優化Widget重建?
- 6. Flutter布局機制
- 7. Row/Column的主軸和交叉軸
- 8. Expanded vs Flexible
- 9. Key的作用與使用場景
- 10. 國際化(i18n)實現
1. 什么是Widget?Flutter中的Widget分為哪幾類?
Widget:Flutter應用的基礎構建單元,描述UI元素的配置(如布局、樣式等)。
- 不可變性:Widget不可變,重建時生成新實例
- 聲明式UI:通過嵌套Widget樹描述界面
主要分類:
類別 | 特點 | 示例 |
---|---|---|
StatelessWidget | 無狀態,屬性不可變 | Text , Icon , Container |
StatefulWidget | 有狀態,可動態更新 | Checkbox , TextField , Slider |
InheritedWidget | 數據共享,跨層級傳遞 | Theme , MediaQuery |
ProxyWidget | 父Widget代理 | ParentDataWidget |
RenderObjectWidget | 底層渲染控制 | Opacity , Transform |
// Widget樹示例
Container( // 布局Widgetpadding: EdgeInsets.all(10),child: Column( // 布局Widgetchildren: [Text('Hello', style: TextStyle(fontSize: 20)), // 無狀態WidgetStatefulCounter() // 有狀態Widget],),
)
2. StatelessWidget和StatefulWidget的區別
特性 | StatelessWidget | StatefulWidget |
---|---|---|
狀態管理 | ? 無內部狀態 | ? 可維護可變狀態 |
重建機制 | 完全重建 | 通過State 對象保留狀態 |
生命周期 | 簡單(僅build) | 復雜(initState/didUpdateWidget等) |
性能 | 更高 | 較低(需維護State) |
使用場景 | 靜態內容 | 交互式組件(表單/動畫) |
典型場景:
- Stateless:顯示靜態文本/圖標
- Stateful:計數器、開關按鈕
3. StatefulWidget生命周期
關鍵方法:
- initState:初始化狀態(調用一次)
- didChangeDependencies:依賴變化時調用(如InheritedWidget更新)
- build:構建UI(必實現)
- didUpdateWidget:父Widget重建時觸發
- setState:通知框架狀態變化(觸發rebuild)
- deactivate:從樹中移除(可能重新插入)
- dispose:永久銷毀,釋放資源
?? 注意:避免在build()
中做耗時操作!
4. 什么是BuildContext?
BuildContext是Widget在樹中位置的引用,核心作用:
查找祖先Widget:
ThemeData theme = Theme.of(context); // 獲取最近的Theme
導航操作:
Navigator.push(context, MaterialPageRoute(...));
Widget狀態管理:
ScaffoldState scaffold = Scaffold.of(context);
scaffold.openDrawer(); // 打開抽屜
重要原則:
- 每個Widget有獨立BuildContext
- Context在Element創建時生成
- 不可緩存Context(可能失效)
5. 如何優化Widget重建?
優化方案 | 實現方式 | 效果 |
---|---|---|
const構造函數 | const Text('Hello') | 避免重復創建相同實例 |
拆分Widget樹 | 將易變部分拆為子Widget | 減少重建范圍 |
使用StatelessWidget | 優先用于靜態內容 | 降低狀態管理開銷 |
Keys的正確使用 | 為列表項/狀態Widget設置Key | 精確控制更新 |
shouldRebuild | @override bool updateShouldNotify | 控制InheritedWidget更新范圍 |
代碼示例:
// 優化前:整個Card重建
Widget build() {return Card(child: HeavyContent(), // 重組件);
}// 優化后:僅變化部分重建
Widget build() {return const Card( // const避免重建child: _HeavyContent(), // 拆分為獨立Widget);
}
6. Flutter布局機制
布局流程(自頂向下):
- 父Widget傳遞約束(constraints: min/max寬高)
- 子Widget確定自身尺寸
- 父Widget定位子Widget(根據alignment/offset)
核心原則:
- 約束驅動:父給子約束,子不能超出約束
- 遞歸布局:深度優先遍歷Widget樹
- 單次布局:每幀最多布局一次
// 布局示例
ConstrainedBox(constraints: BoxConstraints(minWidth: 100, maxHeight: 200), // 父約束child: Container(width: 150, // 子確定尺寸(在約束范圍內)height: 180,),
)
7. Row/Column的主軸和交叉軸
布局組件 | 主軸方向 | 交叉軸方向 |
---|---|---|
Row | 水平(X軸) | 垂直(Y軸) |
Column | 垂直(Y軸) | 水平(X軸) |
主軸對齊(mainAxisAlignment
):
start
/end
/center
/spaceBetween
交叉軸對齊(crossAxisAlignment
):
stretch
/baseline
/start
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, // 主軸均勻分布crossAxisAlignment: CrossAxisAlignment.center, // 交叉軸居中children: [ ... ],
)
8. Expanded vs Flexible
特性 | Expanded | Flexible |
---|---|---|
繼承關系 | Flexible 的子類 | 基礎類 |
flex默認值 | flex=1 | flex=1(可自定義) |
空間占用 | 強制填滿剩余空間 | 按需占用空間 |
fit行為 | 固定FlexFit.tight | 可配置FlexFit.loose |
使用場景:
Row(children: [Container(width: 50), // 固定寬度Expanded( // 占滿剩余寬度child: Text('Expanded Content'),),Flexible( // 按內容寬度占用fit: FlexFit.loose,child: Text('Flexible'),)],
)
9. Key的作用與使用場景
Key的作用:
唯一標識Widget,幫助框架在重建時區分相同類型的Widget
使用場景:
Key類型 | 適用場景 |
---|---|
ValueKey | 列表項(值唯一時) |
ObjectKey | 復雜對象的列表 |
UniqueKey | 強制重建(如動畫重置) |
GlobalKey | 跨組件訪問狀態 |
示例:
ListView.builder(itemBuilder: (ctx, index) {return ListTile(key: ValueKey(items[index].id), // 基于id標識title: Text(items[index].name),);}
)
何時需要Key:
- 動態列表(增刪改操作)
- 保留狀態(如表單輸入框)
- 需要跨組件訪問狀態
10. 國際化(i18n)實現
實現步驟:
- 添加依賴:
dependencies:flutter_localizations:sdk: flutterintl: ^0.17.0
- 創建ARB文件:
**lib/l10n/app_en.arb**
{"hello": "Hello!","@hello": {"description": "歡迎語"}
}
- 生成本地化類:
flutter gen-l10n
- 配置MaterialApp:
MaterialApp(localizationsDelegates: AppLocalizations.localizationsDelegates,supportedLocales: AppLocalizations.supportedLocales,
)
- 使用翻譯:
Text(AppLocalizations.of(context)!.hello)