区分临时状态和应用状态
如何区分临时状态和应用状态。
本文档介绍应用状态、临时状态以及如何在 Flutter 应用中管理它们。
从最广泛的意义上讲,应用程序的状态是指应用程序运行时内存中存在的所有内容。这包括应用程序的资源、Flutter 框架维护的所有关于 UI 的变量、动画状态、纹理、字体等等。虽然这种最广泛的状态定义是有效的,但它对于构建应用程序架构来说用处不大。
首先,你甚至不需要管理某些状态(例如纹理)。框架会为你处理这些。因此,状态的一个更有用的定义是“重建你的 UI 在任何时间点所需的所有数据”。其次,你自己管理的那些状态可以分为两种概念类型:临时状态和应用状态。
临时状态
#临时状态(有时称为UI 状态或局部状态)是指可以整洁地包含在单个 Widget 中的状态。
这,有意地,是一个模糊的定义,所以这里有一些例子。
- 当前页面在
PageView中 - 复杂动画的当前进度
BottomNavigationBar中当前选定的标签
Widget 树的其他部分很少需要访问这种状态。不需要序列化它,并且它不会以复杂的方式改变。
换句话说,不需要对这种状态使用状态管理技术(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 Widget 内部改变。而且,如果用户关闭并重新启动应用程序,你不会介意 _index 重置为零。
应用状态
#不是临时状态,你希望在应用程序的许多部分之间共享的状态,并且你希望在用户会话之间保留的状态,我们称之为应用程序状态(有时也称为共享状态)。
应用程序状态的例子
- 用户偏好设置
- 登录信息
- 社交网络应用程序中的通知
- 电子商务应用程序中的购物车
- 新闻应用程序中文章的已读/未读状态
对于管理应用程序状态,你需要研究你的选项。你的选择取决于应用程序的复杂性和性质、你的团队的先前经验以及许多其他方面。请继续阅读。
没有明确的规则
#明确地说,你可以使用 State 和 setState() 来管理应用程序中的所有状态。事实上,Flutter 团队在许多简单的应用程序示例中都这样做(包括你使用每个 flutter create 获取的启动应用程序)。
情况也相反。例如,你可能会决定——在你的特定应用程序的上下文中——底部导航栏中选定的标签不是临时状态。你可能需要从类外部更改它,在会话之间保留它,等等。在这种情况下,_index 变量是应用程序状态。
没有明确的、普遍的规则来区分某个变量是临时状态还是应用程序状态。有时,你必须将一个重构为另一个。例如,你将从一些明确的临时状态开始,但随着你的应用程序在功能上增长,你可能需要将其移动到应用程序状态。
因此,请带着谨慎的态度看待以下图表
当被问及 React 的 setState 与 Redux 的 store 时,Redux 的作者 Dan Abramov 回答说
"经验法则:做任何不那么尴尬的事情。"
总而言之,任何 Flutter 应用程序中都有两种概念类型的状态。临时状态可以使用 State 和 setState() 实现,并且通常是单个 Widget 的局部状态。其余的是你的应用程序状态。这两种类型在任何 Flutter 应用程序中都有其用途,并且两者之间的划分取决于你自己的偏好和应用程序的复杂性。