1. StatelessWidget
特点
- 无状态组件。
- 适用于不会随时间或用户交互改变的 UI。
生命周期
- 构造函数:用于初始化。
- build() :唯一的方法,构建组件的 UI。
代码示例
class MyStatelessWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('I am Stateless');
}
}
2. StatefulWidget
特点
生命周期
| 方法 | 描述 |
|---|
| 构造函数 | 创建组件实例,通常用于初始化不可变参数。 |
| createState() | 创建 State 对象,组件的状态逻辑由此对象管理。 |
| initState() | State 对象创建时调用,通常用于初始化数据、监听器等。 |
| didChangeDependencies() | 在依赖的 InheritedWidget 发生变化时触发,首次创建时也会调用。 |
| build() | 必须实现的方法,构建组件的 UI。 |
| setState() | 用于更新组件的状态并重新触发 build()。 |
| didUpdateWidget() | 当父组件重新构建,且传入的参数发生变化时触发。 |
| deactivate() | 在 State 被从组件树中临时移除时调用。 |
| dispose() | 在组件销毁时调用,用于清理资源。 |
代码示例
class MyStatefulWidget extends StatefulWidget {
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
@override
void initState() {
super.initState();
print('Init State');
}
@override
Widget build(BuildContext context) {
return Text('I am Stateful');
}
@override
void dispose() {
print('Dispose');
super.dispose();
}
}
StatelessWidget 与 StatefulWidget 总结对比
| 生命周期方法 | StatelessWidget | StatefulWidget |
|---|
createState() | 不适用 | 调用一次 |
initState() | 不适用 | 调用一次 |
didChangeDependencies() | 不适用 | 可选, 当依赖变化时调用 |
build() | 每次构建时调用 | 每次调用 setState() 时都会调用 |
didUpdateWidget() | 不适用 | 当父组件传递新的配置时调用 |
setState() | 不适用 | 用于更新状态并触发 build() |
deactivate() | 不适用 | 当 State 从树中移除时调用 |
dispose() | 不适用 | 当 State 永久从树中移除时调用 |
3. InheritedWidget
特点
- 用于在组件树中共享数据。
- 数据更新时,依赖此数据的子组件会重建。
生命周期
- 构造函数:创建共享数据。
- updateShouldNotify() :判断数据更新时,是否需要通知子组件。
代码示例
class MyInheritedWidget extends InheritedWidget {
final int count;
MyInheritedWidget({required this.count, required Widget child}) : super(child: child);
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) {
return oldWidget.count != count;
}
static MyInheritedWidget? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
}
}
4. RenderObjectWidget
特点
- 低级组件,用于自定义绘制和布局。
- 通常与
RenderBox 搭配使用。
生命周期
- createRenderObject() :创建
RenderObject 实例。
- updateRenderObject() :更新
RenderObject 的状态。
- didUnmountRenderObject() :在组件从树中移除时调用。
代码示例
class MyRenderObjectWidget extends SingleChildRenderObjectWidget {
@override
RenderObject createRenderObject(BuildContext context) {
return RenderBox();
}
@override
void updateRenderObject(BuildContext context, RenderObject renderObject) {
}
}
5. WidgetApp(MaterialApp, CupertinoApp 等)
特点
- 用于管理应用的根组件。
- 包含应用的主题、导航和本地化信息。
生命周期
- 构造函数:初始化根组件。
- build() :构建根组件的 UI。
对比总结
| 特性 | StatelessWidget | StatefulWidget | InheritedWidget | RenderObjectWidget | WidgetApp |
|---|
| 是否有状态 | 否 | 是 | 依赖子组件状态 | 自定义状态 | 否 |
| 复杂性 | 简单 | 中等 | 中等 | 高 | 中等 |
| 生命周期方法数量 | 少(1个) | 多(8+个) | 少(2个) | 中(3个) | 少(1个) |
| 适用场景 | 静态 UI | 动态 UI | 数据共享 | 自定义布局和绘制 | 管理应用的全局配置和导航 |
| 常见用途 | 文本、按钮 | 表单、计数器 | 状态管理 | 高度定制化的 UI | 应用导航、主题 |
选择指南
- 使用
StatelessWidget:当组件是静态的,不会改变状态。
- 使用
StatefulWidget:当需要管理组件内部的状态,比如表单输入、计数器等。
- 使用
InheritedWidget:当需要在组件树中共享数据,比如主题、全局状态。
- 使用
RenderObjectWidget:当需要完全控制组件的绘制和布局。
- 使用
WidgetApp:当需要配置应用的全局设置,比如导航、主题等。