1.1 什么是 Flutter Widget?
在 Flutter 中,一切皆是 Widget。Widget 是 Flutter 用来构建用户界面的基础单位,无论是按钮、文本、布局结构,都是通过 Widget 构建出来的。Flutter 的 UI 是声明式的,Widget 描述了界面在特定状态下的样子。
1.2 Widget 的分类
Widget 在 Flutter 中大致可以分为两类:
- StatelessWidget(无状态的 Widget)
- StatefulWidget(有状态的 Widget)
1.2.1 StatelessWidget(无状态的 Widget)
StatelessWidget 是一种不可变的 Widget,它没有内部状态。其构建函数在创建后不会发生变化,适合用于那些界面固定且不需要随用户交互更新的部分。
class MyStatelessWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text('Hello, StatelessWidget!'),
);
}
}
在这个例子中,MyStatelessWidget
只是展示了一段文本,渲染之后不会发生任何变化。
1.2.2 StatefulWidget(有状态的 Widget)
StatefulWidget 则包含状态,并且可以随着时间、用户交互等动态更新。它由两个部分组成:
- StatefulWidget 类:描述 Widget 的结构。
- State 类:持有该 Widget 的状态,并控制状态的改变如何影响 UI。
class MyStatefulWidget extends StatefulWidget {
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text('Counter: $_counter'),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment'),
),
],
);
}
}
在这个例子中,点击按钮会调用 setState()
方法,该方法会触发 Flutter 重建 MyStatefulWidget
,并更新界面上显示的计数器。
1.3 Widget 的生命周期
StatefulWidget 不仅包含状态,它的生命周期也更为复杂。在开发中,了解 StatefulWidget 的生命周期非常重要,以便在合适的时机初始化资源、更新数据或释放内存。
StatefulWidget 的生命周期主要包括以下几个步骤:
-
createState():在创建 StatefulWidget 时调用,用来创建与这个 Widget 关联的状态对象。
@override _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
-
initState():状态对象被创建时调用。这是初始化的好时机,例如获取数据、订阅服务等。这个方法只会被调用一次。
@override void initState() { super.initState(); // 初始化操作 }
-
didChangeDependencies():当 StatefulWidget 第一次被插入 Widget 树中,或者依赖发生变化时调用。一般用于处理外部依赖的更新。
@override void didChangeDependencies() { super.didChangeDependencies(); // 处理依赖变化 }
-
build():这是最核心的方法,用于描述 Widget 的界面结构。在
setState()
调用后,该方法会被重新执行。@override Widget build(BuildContext context) { return Text('Hello World'); }
-
didUpdateWidget():当父 Widget 重新构建并传递新的参数时调用。可以在这里做一些对比更新操作。
@override void didUpdateWidget(covariant MyStatefulWidget oldWidget) { super.didUpdateWidget(oldWidget); // 处理父组件参数的变化 }
-
deactivate():当 Widget 从 Widget 树中被移除时调用。这是清理资源或取消订阅服务的机会。
@override void deactivate() { super.deactivate(); }
-
dispose():当状态对象从内存中永久移除时调用,用于释放资源、取消监听等操作。这是状态生命周期的最后一步。
@override void dispose() { // 释放资源 super.dispose(); }
这些生命周期方法为开发者提供了在不同阶段控制 Widget 行为的能力,确保在正确的时机进行初始化和资源管理。
1.4 Widget 树与布局
Flutter 的界面由一个嵌套的 Widget 树组成。每个 Widget 可以包含一个或多个子 Widget,形成层次化的结构。通常,最外层的 Widget 是 MaterialApp
或 CupertinoApp
,然后通过 Scaffold
构建页面框架,接着使用 Column
、Row
等布局 Widget 来组织子组件。
示例:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Widget Tree'),
),
body: Column(
children: <Widget>[
Text('Hello, Widget!'),
ElevatedButton(
onPressed: () {},
child: Text('Click me'),
),
],
),
),
);
}
}
在上面的代码中,MyApp
是最外层的根 Widget,接着通过 Scaffold
创建了页面框架。AppBar
是顶部的导航栏,而 Column
是垂直布局,包含一个文本和一个按钮。
1.5 常见基础 Widget
Flutter 提供了丰富的基础 Widget,以下是一些常用的 Widget:
-
Text:显示文本。
Text('Hello World', style: TextStyle(fontSize: 24.0));
-
Container:用于调整尺寸、背景颜色、边距等属性。
Container( padding: EdgeInsets.all(16.0), color: Colors.blue, child: Text('Container Example'), );
-
Row 和 Column:分别用于水平和垂直排列子 Widget。
Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('First'), Text('Second'), ], );
-
Stack:用于将子 Widget 叠加在一起。
Stack( children: <Widget>[ Container(color: Colors.red, width: 100, height: 100), Container(color: Colors.green, width: 50, height: 50), ], );
-
ListView:创建可滚动的列表。
ListView( children: <Widget>[ ListTile(title: Text('Item 1')), ListTile(title: Text('Item 2')), ListTile(title: Text('Item 3')), ], );
1.6 小结
在本章中,我们详细讨论了 Flutter 中 Widget 的概念、分类及其生命周期。理解 Widget 的生命周期对于正确管理资源、优化性能、处理异步数据流至关重要。StatelessWidget 适用于不需要管理状态的场景,而 StatefulWidget 则允许我们通过状态管理来动态更新 UI。
下一章我们将深入探讨如何使用布局 Widget 构建复杂的界面,以及不同的布局策略。