跳至主要内容

区分短暂状态和应用状态

本文介绍了应用程序状态、短暂状态以及如何在 Flutter 应用程序中管理它们。

从最广义的角度来看,应用程序的状态是在应用程序运行时内存中存在的一切。这包括应用程序的资源、Flutter 框架维护的所有 UI 相关变量、动画状态、纹理、字体等等。虽然这种最广泛的状态定义是有效的,但对于构建应用程序来说并不实用。

首先,您甚至无法管理某些状态(例如纹理)。框架会为您处理这些状态。因此,更有用的状态定义是“在任何时间点重建 UI 所需的任何数据”。其次,您自己管理的状态可以分为两种概念类型:短暂状态和应用程序状态。

短暂状态

#

短暂状态(有时称为UI 状态本地状态)是可以整齐地包含在一个单个 widget 中的状态。

这是一个有意模糊的定义,以下是一些示例。

  • PageView 中的当前页面
  • 复杂动画的当前进度
  • BottomNavigationBar 中当前选定的选项卡

widget 树的其他部分很少需要访问此类状态。无需对其进行序列化,并且它不会以复杂的方式更改。

换句话说,无需在此类状态上使用状态管理技术(ScopedModel、Redux 等)。您只需要一个StatefulWidget

下面,您将看到底部导航栏中当前选定的项目是如何保存在_MyHomepageState类的_index字段中的。在此示例中,_index是短暂状态。

dart
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的状态类中的字段是完全自然的。应用程序的任何其他部分都不需要访问_index。该变量仅在MyHomepage widget 内部更改。而且,如果用户关闭并重新启动应用程序,您不介意_index重置为零。

应用状态

#

非短暂状态,您希望在应用程序的许多部分共享的状态,以及您希望在用户会话之间保留的状态,我们称之为应用程序状态(有时也称为共享状态)。

应用程序状态示例

  • 用户偏好设置
  • 登录信息
  • 社交网络应用程序中的通知
  • 电子商务应用程序中的购物车
  • 新闻应用程序中文章的已读/未读状态

为了管理应用程序状态,您需要研究您的选择。您的选择取决于应用程序的复杂性和性质、团队之前的经验以及许多其他方面。继续阅读。

没有明确的规则

#

需要明确的是,您可以使用StatesetState()来管理应用程序中的所有状态。事实上,Flutter 团队在许多简单的应用程序示例中都使用了这种方法(包括您使用每个flutter create获得的启动应用程序)。

反过来也一样。例如,您可能会决定——在您的特定应用程序上下文中——底部导航栏中选定的选项卡不是短暂状态。您可能需要从外部更改它,在会话之间保留它,等等。在这种情况下,_index变量是应用程序状态。

没有明确的、普遍的规则来区分特定变量是短暂状态还是应用程序状态。有时,您需要将其中一个重构为另一个。例如,您将从一些明显是短暂的状态开始,但随着应用程序功能的增长,可能需要将其移动到应用程序状态。

因此,请谨慎看待以下图表

A flow chart. Start with 'Data'. 'Who needs it?'. Three options: 'Most widgets', 'Some widgets' and 'Single widget'. The first two options both lead to 'App state'. The 'Single widget' option leads to 'Ephemeral state'.

当被问及 React 的 setState 与 Redux 的 store 时,Redux 的作者 Dan Abramov 回答道

“经验法则是:做任何不那么尴尬的事情。”

总之,任何 Flutter 应用程序中都有两种概念上的状态类型。短暂状态可以使用StatesetState()实现,并且通常位于单个 widget 中。其余的是您的应用程序状态。这两种类型在任何 Flutter 应用程序中都有其位置,并且两者之间的划分取决于您自己的偏好和应用程序的复杂性。