📅  最后修改于: 2023-12-03 14:41:15.357000             🧑  作者: Mango
Flutter 是谷歌推出的一款跨平台移动应用开发框架。Flutter 可以让你在一套代码基础下同时开发 iOS 和 Android 应用程序,同时降低项目成本和维护难度。其中,StatefulWidget 是 Flutter 中的一个重要组件,它使得 Flutter 应用程序可以拥有动态的 UI,能够根据事件、用户交互等修改内部状态,实现复杂的应用逻辑。本文将介绍 StatefulWidget 的基本用法和常用方法。
在 Flutter 中,有 Stateful 和 Stateless 两种 Widget。StatelessWidget 不可变,一旦被创建便无法修改属性和状态,而 StatefulWidget 可以在属性、事件、动画等各种情况下修改内部状态。换言之,StatefulWidget 允许我们根据 UI 的变化而变化,StatelessWidget 一旦创建就不会再变了。
因此,如果我们需要的是一个简单的静态组件,StatelessWidget 是最佳的选择。它的构建会更快,也更容易维护。但是如果你需要对组件进行动态更新,例如增加计数器的值,使用 StatefulWidget 会更加合适。
下面是 StatefulWidget 的基本代码结构:
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({ Key? key }) : super(key: key);
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
@override
Widget build(BuildContext context) {
return Container(
child: Text('Hello, World!'),
);
}
}
代码中,我们定义了一个 MyStatefulWidget StatefulWidget 组件,并在其中添加了一个内部State类 _MyStatefulWidgetState。当父组件 MyStatefulWidget 第一次创建时,_MyStatefulWidgetState 也会被创建。我们可以通过实现 _MyStatefulWidgetState 类,添加需要响应状态的方法,来创建一个可以动态改变的组件。
当 StatefulWidget 被创建时,会按照如下顺序调用一些方法:
createState()
:这是 StatefulWidget 创建时唯一被调用的方法,用于创建 StatefulWidget 的状态(State)。
initState()
:此方法在 State 对象被创建后调用,并在 State 对象与 BuildContext 对象相关联时调用。
执行 build()
方法,返回渲染 UI(Widget)
将 StatefulWidget 从屏幕上删除时,会按照如下顺序调用一些方法:
deactivate()
:在组件被移除前调用,用于清除资源(例如:停止动画)。
destroyState()
:在 State 被永久删除之前调用,释放资源。
除此之外,Flutter 还提供了一个 dispose()
方法,用于处理那些不能被监听者监听到的资源清除,例如:正在进行中的动画。此方法的调用时机是在 destroyState()
调用后,即 State 被彻底销毁时。
StatefulWidget 的状态保存在其对应的 State 里面。那么我们如何获取这个 State 对象呢?
我们可以通过 context
获取到构建当前 StatefulWidget 的 _MyStatefulWidgetState,代码如下:
_MyStatefulWidgetState state = context.findAncestorStateOfType<_MyStatefulWidgetState>();
值得注意的是,如果我们在一个异步任务中访问 state,其状态可能已经被修改,此时访问已经失效,因此我们应该尽量少量地关注 state 的细节。
在上文中,我们提到了 StatefulWidget 之所以能够动态更新 UI,是因为它的内部状态可以被修改。那么如何在组件内部改变状态呢?这就引出了 StatefulWidget 的核心方法 setState()
。
setState()
方法接受一个参数,这个参数是一个无返回值的回调函数。当这个回调函数执行完毕之后,Flutter 就会自动重新调用 build()
方法。
下面是一个例子:
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
在这个例子中,我们定义了一个 _counter
变量来保存按钮被按下的次数,并在 Build 方法中使用了 _counter
的值。当用户按下 FloatingAction button 按钮后,_incrementCounter()
方法被调用,设置了 _counter
的值,setState() 方法被调用,重新调用 Build 方法重新渲染 UI。
注意:我们不能直接使用 _counter
按钮值的更改会没有反应,提示我们需要调用 setState()
。
更多关于 Flutter 的使用介绍,可以参考官方文档:https://flutter.dev/docs.