目录
- 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)