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