区分暂时性状态与应用状态
本文档介绍了应用状态、暂时性状态,以及如何在 Flutter 应用中管理它们。
从最广泛的意义上讲,应用的状态是指应用运行时内存中存在的一切。这包括应用的资源、Flutter 框架维护的关于 UI 的所有变量、动画状态、纹理、字体等等。虽然这种最广泛的状态定义是有效的,但对于架构应用来说并不是很有用。
首先,有些状态(如纹理)你甚至不需要管理。框架会为你处理这些。因此,一个更有用的状态定义是“你在任何时刻重建 UI 所需的任何数据”。其次,你确实需要自己管理的状态可以分为两种概念类型:暂时性状态和应用状态。
暂时性状态
#暂时性状态(有时称为*UI 状态*或*局部状态*)是你可以在单个小部件中整齐地包含的状态。
这是一个有意模糊的定义,以下是一些例子。
PageView
中的当前页面- 复杂动画的当前进度
BottomNavigationBar
中当前选中的选项卡
小部件树的其他部分很少需要访问这种状态。它不需要序列化,也不会以复杂的方式改变。
换句话说,不需要对此类状态使用状态管理技术(ScopedModel、Redux 等)。你只需要一个 StatefulWidget
。
下面,你将看到底部导航栏中当前选定的项目如何保存在 _MyHomepageState
类的 _index
字段中。在此示例中,_index
是暂时性状态。
class MyHomepage extends StatefulWidget {
const MyHomepage({super.key});
@override
State<MyHomepage> createState() => _MyHomepageState();
}
class _MyHomepageState extends State<MyHomepage> {
int _index = 0;
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
currentIndex: _index,
onTap: (newIndex) {
setState(() {
_index = newIndex;
});
},
// ... items ...
);
}
}
在这里,使用 setState()
和 StatefulWidget 的 State 类中的字段是完全自然的。应用的其他任何部分都不需要访问 _index
。该变量只在 MyHomepage
小部件内部改变。而且,如果用户关闭并重新启动应用,你也不介意 _index
重置为零。
应用状态
#不是暂时性的状态,你希望在应用的许多部分共享,并希望在用户会话之间保持,我们称之为应用状态(有时也称为共享状态)。
应用状态的例子
- 用户偏好设置
- 登录信息
- 社交网络应用中的通知
- 电子商务应用中的购物车
- 新闻应用中文章的已读/未读状态
为了管理应用状态,你需要研究你的选择。你的选择取决于应用的复杂性和性质、团队之前的经验以及许多其他方面。请继续阅读。
没有明确的规则
#需要明确的是,你*可以*使用 State
和 setState()
来管理应用中的所有状态。事实上,Flutter 团队在许多简单的应用示例中(包括每次 flutter create
都会得到的起始应用)都是这样做的。
反之亦然。例如,你可能会决定——在你的特定应用的上下文中——底部导航栏中选中的选项卡*不是*暂时性状态。你可能需要从类外部改变它,在会话之间保持它,等等。在这种情况下,_index
变量就是应用状态。
没有一个明确的、普遍的规则来区分某个特定变量是暂时性状态还是应用状态。有时,你必须将一种状态重构为另一种。例如,你可能从一些明显的暂时性状态开始,但随着应用功能增长,它可能需要移动到应用状态。
因此,对下图要持保留态度。

当被问及 React 的 setState 与 Redux 的 store 时,Redux 的作者 Dan Abramov 回答道:
“经验法则是:选择最不麻烦的。”
总而言之,任何 Flutter 应用中都有两种概念上的状态类型。暂时性状态可以使用 State
和 setState()
来实现,并且通常是单个小部件的局部状态。其余的是你的应用状态。这两种类型在任何 Flutter 应用中都有其位置,两者之间的划分取决于你自己的偏好和应用的复杂性。