目录
- [1. 什么是Widget?Flutter中的Widget分为哪几类?](#1. 什么是Widget?Flutter中的Widget分为哪几类?)
- [2. StatelessWidget和StatefulWidget的区别](#2. StatelessWidget和StatefulWidget的区别)
- [3. StatefulWidget生命周期](#3. StatefulWidget生命周期)
- [4. 什么是BuildContext?](#4. 什么是BuildContext?)
- [5. 如何优化Widget重建?](#5. 如何优化Widget重建?)
- [6. Flutter布局机制](#6. Flutter布局机制)
- [7. Row/Column的主轴和交叉轴](#7. Row/Column的主轴和交叉轴)
- [8. Expanded vs Flexible](#8. Expanded vs Flexible)
- [9. Key的作用与使用场景](#9. Key的作用与使用场景)
- [10. 国际化(i18n)实现](#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 |
dart
// Widget树示例
Container( // 布局Widget
padding: EdgeInsets.all(10),
child: Column( // 布局Widget
children: [
Text('Hello', style: TextStyle(fontSize: 20)), // 无状态Widget
StatefulCounter() // 有状态Widget
],
),
)
2. StatelessWidget和StatefulWidget的区别
特性 | StatelessWidget | StatefulWidget |
---|---|---|
状态管理 | ❌ 无内部状态 | ✅ 可维护可变状态 |
重建机制 | 完全重建 | 通过State 对象保留状态 |
生命周期 | 简单(仅build) | 复杂(initState/didUpdateWidget等) |
性能 | 更高 | 较低(需维护State) |
使用场景 | 静态内容 | 交互式组件(表单/动画) |
典型场景:
- Stateless:显示静态文本/图标
- Stateful:计数器、开关按钮
3. StatefulWidget生命周期
是 否 createState initState didChangeDependencies build didUpdateWidget? deactivate dispose
关键方法:
- initState:初始化状态(调用一次)
- didChangeDependencies:依赖变化时调用(如InheritedWidget更新)
- build:构建UI(必实现)
- didUpdateWidget:父Widget重建时触发
- setState:通知框架状态变化(触发rebuild)
- deactivate:从树中移除(可能重新插入)
- dispose:永久销毁,释放资源
⚠️ 注意 :避免在build()
中做耗时操作!
4. 什么是BuildContext?
BuildContext 是Widget在树中位置的引用,核心作用:
查找祖先Widget:
dart
ThemeData theme = Theme.of(context); // 获取最近的Theme
导航操作:
dart
Navigator.push(context, MaterialPageRoute(...));
Widget状态管理:
dart
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更新范围 |
代码示例:
dart
// 优化前:整个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树
- 单次布局:每帧最多布局一次
dart
// 布局示例
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
dart
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 |
使用场景:
dart
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 | 跨组件访问状态 |
示例:
dart
ListView.builder(
itemBuilder: (ctx, index) {
return ListTile(
key: ValueKey(items[index].id), // 基于id标识
title: Text(items[index].name),
);
}
)
何时需要Key:
- 动态列表(增删改操作)
- 保留状态(如表单输入框)
- 需要跨组件访问状态
10. 国际化(i18n)实现
实现步骤:
- 添加依赖:
yaml
dependencies:
flutter_localizations:
sdk: flutter
intl: ^0.17.0
- 创建ARB文件 :
**lib/l10n/app_en.arb**
json
{
"hello": "Hello!",
"@hello": {"description": "欢迎语"}
}
- 生成本地化类:
shell
flutter gen-l10n
- 配置MaterialApp:
dart
MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
)
- 使用翻译:
dart
Text(AppLocalizations.of(context)!.hello)