前面几节已经介绍了Flutter的布局、文本、输入、按钮、图片等部件,通过前面几个小节我们对Flutter构建界面已经了基本的认识,并且能够构建基本的静态界面。但是,作为一个应用肯定不止展示静态界面这么单一,我们还需要UI能够响应各种状态。
Flutter核心参考React,作为一种响应式UI框架,都会涉及到一个永恒的主题——“状态(State)管理”。Flutter 中的状态管理是构建应用程序的关键部分,它允许你有效地管理应用程序中的数据和状态,并确保 UI 在数据变化时得到正确更新。
状态管理方式
那么状态管理分为哪些呢?以下是管理状态的最常见的方式:
- Widget 管理自己的状态。
- Widget 管理子 Widget 状态。
- 混合管理(父 Widget 和子 Widget 都管理状态)。
如何决定使用哪种管理方法?下面是官方给出的一些原则可以帮助你做决定:
- 如果状态是用户数据,如复选框的选中状态、滑块的位置,则该状态最好由父 Widget 管理。
- 如果状态是有关界面外观效果的,例如颜色、动画,那么状态最好由 Widget 本身来管理。
- 如果某一个状态是不同 Widget 共享的则最好由它们共同的父 Widget 管理。
在 Widget 内部管理状态封装性会好一些,而在父 Widget 中管理会比较灵活。有些时候,如果不确定到底该怎么管理状态,那么推荐的首选是在父 Widget 中管理(灵活会显得更重要一些)。
状态(state)
在Flutter中,状态(state)是指部件(widget)的可变数据或配置,它们决定了部件在屏幕上的显示样式和行为。状态可以是两种类型之一:有状态的(Stateful)和无状态的(Stateless)。而对应这两种状态的部件类型分别是:StatefulWidget 和 StatelessWidget。它们分别用于管理有状态和无状态的小部件。以下是它们的简要介绍:
2.1 StatelessWidget(无状态小部件):
- StatelessWidget 是一个不可变的小部件,它的属性值在构建时被确定,并且在整个生命周期内保持不变。
- 通常用于显示静态内容,不需要根据数据的变化来更新 UI。
- 无法保存状态,因此适合用于显示不会改变的 UI。
示例代码:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Text('Hello, World!'),
);
}
}
2.2 StatefulWidget(有状态小部件):
- StatefulWidget 是一个可变的小部件,它可以保存状态,并在状态发生变化时重新构建 UI。
- 通常用于包含动态数据的 UI,需要根据数据变化来更新。
- 使用 State 类来保存状态,并通过 setState 方法来通知 Flutter 框架进行 UI 更新。
示例代码:
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Counter: $_counter'),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment'),
),
],
);
}
}
StatefulWidget 和 State:
- StatefulWidget 是一个可变的小部件,它管理着与用户交互和其他数据变化相关的状态。
- 每个 StatefulWidget 都有一个对应的 State 对象,State 对象负责管理和更新小部件的状态,并在状态变化时重新构建UI。
setState 方法:
- setState 方法是 State 类的一个成员方法,用于通知Flutter框架重新构建UI。
- 当状态发生变化时,调用 setState 方法可以更新UI,从而反映出状态的变化。
StatelessWidget 用于静态 UI,而 StatefulWidget 用于动态 UI。选择合适的小部件类型取决于你的 UI 是否需要响应数据变化。所以,涉及到状态管理的我们都会使用StatefulWidget,后面的部分示例代码都是以StatefulWidget作为载体。
局部状态
在 Flutter 中,您可以使用 StatefulWidget 和 State 来实现局部状态管理。下面是一个简单的教程,演示如何在 Flutter 中使用 StatefulWidget 和 State 来管理局部状态:
import 'package:flutter/material.dart';
class CounterWidget extends StatefulWidget {
@override
_CounterWidgetState createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter: $_counter',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 16),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment'),
),
],
);
}
}
在上面的示例中,CounterWidget 是一个 StatefulWidget,它管理一个 _counter 变量作为其状态。当用户点击增加按钮时,_incrementCounter 方法会被调用,它调用 setState() 来更新 _counter,从而通知 Flutter 框架重新构建UI,反映出状态的变化。
这是一个简单的例子,演示了如何在 Flutter 中使用 StatefulWidget 和 State 来实现局部状态管理。
父Widget管理子Widget的状态
在 Flutter 中,父组件管理子组件状态是一种常见的状态管理模式,适用于一些特定场景,例如当多个子组件需要共享状态时,或者当子组件需要将其状态提升到父组件中进行管理时。以下是一个简单的示例,演示了如何在 Flutter 中实现父组件管理子组件状态:
- 创建一个父组件,定义并管理状态:
class ParentWidget extends StatefulWidget {
@override
_ParentWidgetState createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
void _resetCounter() {
setState(() {
_counter = 0;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter in Parent Widget: $_counter',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 16),
ChildWidget(counter: _counter, onReset: _resetCounter),
],
);
}
}
- 创建一个子组件,接受父组件传递的状态并进行渲染:
class ChildWidget extends StatelessWidget {
final int counter;
final VoidCallback onReset;
ChildWidget({required this.counter, required this.onReset});
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(
'Counter in Child Widget: $counter',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 16),
ElevatedButton(
onPressed: onReset,
child: Text('Reset'),
),
],
);
}
}
在上面的示例中,
- ParentWidget 是一个 StatefulWidget,它管理一个 _counter 变量作为其状态,ParentWidget将_counter作为参数传递给 ChildWidget ;
- 当用户点击 ChildWidget 中的重置按钮时,ChildWidget 通过回调将事件传递给 ParentWidget,ParentWidget 调用_resetCounter()方法更新 _counter,并通知 Flutter 框架重新构建 UI。
这种模式下,父组件负责管理子组件的状态,并将状态通过属性传递给子组件,子组件则负责渲染UI并处理用户操作,并通过回调将事件传递给父组件。
混合管理
在 Flutter 中,父子组件状态混合管理是一种常见的状态管理模式,适用于复杂的应用程序结构,其中某些状态需要在父组件和子组件之间共享和管理。这种模式结合了父组件管理和子组件自管理状态的优点,可以灵活地应对不同的场景需求。以下是一个示例,演示了如何在 Flutter 中实现父子组件状态混合管理:
- 创建一个父组件,定义并管理部分状态:
class ParentWidget extends StatefulWidget {
@override
_ParentWidgetState createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
int _parentCounter = 0;
void _incrementParentCounter() {
setState(() {
_parentCounter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter in Parent Widget: $_parentCounter',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 16),
ChildWidget(
parentCounter: _parentCounter,
onIncrementParentCounter: _incrementParentCounter,
),
],
);
}
}
- 创建一个子组件,接受父组件传递的部分状态并进行渲染,并维护自己的一部分状态:
class ChildWidget extends StatefulWidget {
final int parentCounter;
final VoidCallback onIncrementParentCounter;
ChildWidget({
required this.parentCounter,
required this.onIncrementParentCounter,
});
@override
_ChildWidgetState createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
int _childCounter = 0;
void _incrementChildCounter() {
setState(() {
_childCounter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(
'Counter in Child Widget: $_childCounter',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 16),
ElevatedButton(
onPressed: () {
widget.onIncrementParentCounter();
_incrementChildCounter();
},
child: Text('Increment Both Counters'),
),
SizedBox(height: 16),
Text(
'Parent Counter in Child Widget: ${widget.parentCounter}',
style: TextStyle(fontSize: 16),
),
],
);
}
}
在上面的示例中,
- ParentWidget 管理了一个 _parentCounter 变量作为其状态,并将其传递给 ChildWidget。
- ChildWidget 管理了一个 _childCounter 变量作为其局部状态,并在用户点击按钮时更新它。当用户点击按钮时,ChildWidget 调用了父组件传递的回调函数 onIncrementParentCounter,同时更新了自己的 _childCounter 状态。
- 这样父子组件状态得以混合管理,既能共享父组件的状态,又能管理自己的一部分状态。
全局状态
在 Flutter 中,State 类和 StatefulWidget 通常用于管理部件的状态,而不是全局状态。State 对象是与特定部件相关联的,而 StatefulWidget 只在其自身范围内管理状态。所以我们通过state很难实现对全局状态的管理,那么Flutter中有哪些方式能进行全局状态管理呢?这就留给后面的章节再进行讲解。
小结
在 Flutter 中,状态管理是构建应用程序的重要部分之一。以下是关于 Flutter 状态管理的一些重要要点小结:
StatefulWidget 和 State:
- StatefulWidget 用于创建具有可变状态的小部件。
- State 对象负责管理与小部件相关的状态数据,并在状态发生变化时通知 Flutter 框架重新构建 UI。
setState 方法:
- setState 方法是 State 类的一个成员方法,用于通知 Flutter 框架重新构建 UI。
- 当状态发生变化时,调用 setState 方法可以更新 UI,反映出状态的变化。
局部状态管理:
- 在小部件范围内管理状态的模式称为局部状态管理。
- 可以使用 StatefulWidget 和 State 来实现局部状态管理,将状态存储在小部件中,并在小部件自身范围内进行管理和更新。
父组件管理子组件状态:
- 将子组件的状态提升到其共同的父组件中进行管理。
- 父组件通过 props 将状态传递给子组件。
- 子组件可以通过回调函数(callbacks)将事件传递给父组件,从而修改父组件中的状态。
- 父组件管理子组件适用于需要共享状态或处理子组件之间交互的场景,可以帮助保持组件之间的解耦,使代码更易于理解和维护。
选择适合的状态管理方法:
- 根据应用程序的需求、复杂度和团队技术栈选择适合的状态管理方法。
- 局部状态管理适用于管理特定小部件的状态,而全局状态管理适用于共享和管理整个应用程序的状态。
综上所述,Flutter 状态管理是构建应用程序的关键部分之一,了解不同的状态管理方法和模式有助于您选择合适的方法来管理和共享应用程序的状态,从而提高代码的可维护性和可扩展性。
本文暂时没有评论,来添加一个吧(●'◡'●)