Widget概述 #
一、什么是Widget #
1.1 Widget定义 #
在Flutter中,Widget是UI的基本构建块。一切皆Widget,从按钮到布局,从字体到动画,都是由Widget组成的。
dart
Text('Hello, Flutter!')
Container(
padding: EdgeInsets.all(16),
child: Text('Hello'),
)
1.2 Widget特点 #
| 特点 | 说明 |
|---|---|
| 不可变 | Widget一旦创建,属性不可改变 |
| 轻量 | Widget是轻量级的数据配置 |
| 树形结构 | Widget组成树形结构 |
| 组合优先 | 通过组合构建复杂UI |
1.3 Widget分类 #
text
Widget
├── StatelessWidget(无状态)
├── StatefulWidget(有状态)
├── RenderObjectWidget(渲染)
│ ├── SingleChildRenderObjectWidget
│ ├── MultiChildRenderObjectWidget
│ └── LeafRenderObjectWidget
└── ProxyWidget(代理)
├── InheritedWidget
└── ParentDataWidget
二、Widget树 #
2.1 三棵树 #
Flutter应用由三棵树组成:
text
Widget树 Element树 RenderObject树
│ │ │
Text ──────────→ TextElement ──────→ RenderParagraph
│ │ │
Container ─────→ ContainerElement ─→ RenderDecoratedBox
│ │ │
Column ────────→ ColumnElement ─────→ RenderFlex
| 树 | 说明 |
|---|---|
| Widget树 | 描述UI配置 |
| Element树 | 管理Widget生命周期 |
| RenderObject树 | 负责布局和绘制 |
2.2 树的关系 #
dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My App'),
),
body: Center(
child: Text('Hello'),
),
),
);
}
}
三、StatelessWidget #
3.1 定义 #
StatelessWidget是不可变的Widget,一旦创建就不可改变。
dart
class MyCard extends StatelessWidget {
final String title;
final String subtitle;
const MyCard({
super.key,
required this.title,
this.subtitle = '',
});
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.headlineSmall,
),
if (subtitle.isNotEmpty)
Text(
subtitle,
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
);
}
}
3.2 使用场景 #
- 纯展示组件
- 不需要管理状态
- 父Widget传递的数据不变
3.3 最佳实践 #
dart
class UserProfile extends StatelessWidget {
final User user;
const UserProfile({
super.key,
required this.user,
});
@override
Widget build(BuildContext context) {
return Column(
children: [
CircleAvatar(
backgroundImage: NetworkImage(user.avatarUrl),
),
SizedBox(height: 8),
Text(
user.name,
style: Theme.of(context).textTheme.titleLarge,
),
Text(
user.email,
style: Theme.of(context).textTheme.bodySmall,
),
],
);
}
}
四、StatefulWidget #
4.1 定义 #
StatefulWidget是可以有状态的Widget,状态可以改变并触发UI更新。
dart
class Counter extends StatefulWidget {
const Counter({super.key});
@override
State<Counter> createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _count = 0;
void _increment() {
setState(() {
_count++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Count: $_count'),
ElevatedButton(
onPressed: _increment,
child: Text('Increment'),
),
],
);
}
}
4.2 State生命周期 #
text
createState()
│
▼
initState() ──────────────────┐
│ │
▼ │
didChangeDependencies() │
│ │
▼ │
build() ◄──────────────────────┤
│ │
▼ │
didUpdateWidget() │ setState()
│ │
▼ │
setState() ────────────────────┘
│
▼
deactivate()
│
▼
dispose()
4.3 生命周期方法 #
dart
class MyWidget extends StatefulWidget {
final String title;
const MyWidget({super.key, required this.title});
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late TextEditingController _controller;
@override
void initState() {
super.initState();
_controller = TextEditingController();
print('initState');
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
print('didChangeDependencies');
}
@override
void didUpdateWidget(MyWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.title != widget.title) {
print('Title changed: ${widget.title}');
}
}
@override
void dispose() {
_controller.dispose();
print('dispose');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
child: Text(widget.title),
);
}
}
4.4 生命周期方法说明 #
| 方法 | 说明 |
|---|---|
| initState | 初始化状态,只调用一次 |
| didChangeDependencies | 依赖变化时调用 |
| build | 构建Widget树 |
| didUpdateWidget | 父Widget重建时调用 |
| setState | 触发重建 |
| deactivate | 从树中移除时调用 |
| dispose | 永久移除时调用 |
五、Widget与State的关系 #
5.1 Widget是不可变的 #
dart
class MyButton extends StatelessWidget {
final String text;
final VoidCallback? onPressed;
const MyButton({
super.key,
required this.text,
this.onPressed,
});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
child: Text(text),
);
}
}
5.2 State是可变的 #
dart
class ToggleButton extends StatefulWidget {
final String onText;
final String offText;
const ToggleButton({
super.key,
this.onText = 'ON',
this.offText = 'OFF',
});
@override
State<ToggleButton> createState() => _ToggleButtonState();
}
class _ToggleButtonState extends State<ToggleButton> {
bool _isOn = false;
void _toggle() {
setState(() {
_isOn = !_isOn;
});
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _toggle,
child: Text(_isOn ? widget.onText : widget.offText),
);
}
}
5.3 访问Widget属性 #
在State中通过 widget 属性访问Widget的属性:
dart
class _MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
return Text(widget.title);
}
}
六、Key #
6.1 Key的作用 #
Key用于标识Widget,帮助Flutter识别Widget是否改变。
dart
class TodoList extends StatelessWidget {
final List<String> todos;
const TodoList({super.key, required this.todos});
@override
Widget build(BuildContext context) {
return Column(
children: todos.map((todo) {
return ListTile(
key: ValueKey(todo),
title: Text(todo),
);
}).toList(),
);
}
}
6.2 Key类型 #
| Key类型 | 说明 |
|---|---|
| ValueKey | 使用值作为标识 |
| ObjectKey | 使用对象作为标识 |
| UniqueKey | 每次创建唯一标识 |
| GlobalKey | 全局唯一标识 |
6.3 GlobalKey #
dart
class MyForm extends StatefulWidget {
@override
State<MyForm> createState() => MyFormState();
}
class MyFormState extends State<MyForm> {
final _formKey = GlobalKey<FormState>();
void submit() {
if (_formKey.currentState!.validate()) {
print('Form is valid');
}
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter text';
}
return null;
},
),
ElevatedButton(
onPressed: submit,
child: Text('Submit'),
),
],
),
);
}
}
七、Widget通信 #
7.1 父传子 #
dart
class ParentWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChildWidget(
message: 'Hello from parent',
count: 10,
);
}
}
class ChildWidget extends StatelessWidget {
final String message;
final int count;
const ChildWidget({
super.key,
required this.message,
required this.count,
});
@override
Widget build(BuildContext context) {
return Text('$message: $count');
}
}
7.2 子传父(回调) #
dart
class ParentWidget extends StatefulWidget {
@override
State<ParentWidget> createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
String _message = 'Waiting...';
void _onMessageReceived(String message) {
setState(() {
_message = message;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text(_message),
ChildWidget(onMessage: _onMessageReceived),
],
);
}
}
class ChildWidget extends StatelessWidget {
final Function(String) onMessage;
const ChildWidget({super.key, required this.onMessage});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => onMessage('Hello from child'),
child: Text('Send Message'),
);
}
}
7.3 兄弟组件通信 #
dart
class ParentWidget extends StatefulWidget {
@override
State<ParentWidget> createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
int _counter = 0;
void _increment() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
DisplayWidget(count: _counter),
ControlWidget(onIncrement: _increment),
],
);
}
}
八、总结 #
8.1 核心要点 #
| 要点 | 说明 |
|---|---|
| Widget | UI的基本构建块 |
| StatelessWidget | 无状态Widget |
| StatefulWidget | 有状态Widget |
| State | 管理可变状态 |
| Key | Widget标识 |
| 生命周期 | initState → build → dispose |
8.2 下一步 #
了解了Widget概述后,让我们学习 基础Widget!
最后更新:2026-03-28