Skip to content

Latest commit

 

History

History
100 lines (52 loc) · 6.58 KB

Flutter-StateM.md

File metadata and controls

100 lines (52 loc) · 6.58 KB

原文链接: https://levelup.gitconnected.com/flutter-state-management-in-2021-when-to-use-what-98722093b8bc

有时候选择比较少也是一件好事,例如在 React 中通常只盛行一到两个状态管理解决方案,而Flutter 自从 2020 年末开始,每个月似乎都有新的状态管理方案出现,因此这里主要罗列出它们的一些优劣,从而帮助你选择最适合的状态管理方案。

基础

一般在无需修改 pubspec.yaml文件的情况下,你默认有两种状态管理解决方案可以选择,大多数时候这就足够了。

setState

setState 仅在本地范围内有效,如果一个 Widget 需要改变它自己的状态,那么 setState 就是你最好的选择。

例如:修改开关是打开还是关闭,或者存储改变正在输入的文本内容,这种场景你真的不需要考虑任何其它状态管理包

我的经验法则是:如果只在此 Widget 中需要有状态变量,或者在该控件树下恰好只有 1 个上下的 Widget,则它属于本地范围,这时候直接使用 StatefulWidget 是最合适不过。

如果你需要将状态在控件树内向下传递树,那么只需将变量放在子 Widget 的构造函数中;如果相同的变量需要传递到 2+ Widget 的构造函数,那么这时候才需要研究更高范围的状态管理。

InheretedWidget

前面我们在 setState 中讨论的那个开关,如果它是控制应用是处于暗模式还是亮模式,如果在这种情况下,你就需要将状态提升到可以更好地沿控件树传播的某个位置。

而在你使用第三方框架去完成这个需求时,让我们看一下 InheretedWidget

InheretedWidget 允许它下面的任何 Widget 访问它的属性,这意味着可以有一个变量,例如:

enum Theme {
  dark,
  light 
}

InheretedWidget 内部,任何与主题有关的 Widget 都可以通过 MyInheretedWidget.of(context).theme 访问主题,并且该Widget 还会在主题更新时自动重建。

直接使用 InheretedWidget 不好的地方在于会有很多样板,Widget 系统有大量重复的代码。

你需要安装的那些

BLoC (Cubit?)

Bloc 可能是 Flutter 中状态管理最古老的解决方案之一(不考虑 scoped_model 的话),并且现在看来仍然还不错。

最近 BLoC 已将 Cubit 添加到组合中,这使得 BLoC 或多或少不会显得过气,因为 Cubit 降低了所需的样板,这意味着以后迁移更容易,而在我看来 BLoC 在这两个不同的领域中表现出色:

1、与团队合作

BLoC不灵活 方面做得非常好,可能对于很多人来说这是一件坏事:他们希望能更快速地更改他们的应用,而无需编写或更改太多代码。

但是对于团队来说情况并非如此:通过让事情变得不灵活,你可以保证一切都按照最初开发人员的预期工作——例如 BLoC 中的状态仅仅有 1、2 和 3 这样的值,你在使用 BLoC 更改为这些值时,其他程序员不会意外地将其值移动到 4,这就是它不灵活的好处。

1、事件驱动状态

BLoC 是基于事件驱动的,你必须定义你的事件,执行 API 调用可能会触发一个事件,该事件会推出一个 CallingAPIState 的 state,然后当 API 调用完成时,它会推出一个HaveAPIResultsState.

如果你想严格定义你的事件和状态,那么 BLoC 很适合你,如果你需要灵活性和开发速度,那么 BLoC 可能不是正确的选择。

Provider

出于遗留原因这里将 Provider 列入介绍,它很简单,很干净,很棒……但有一些缺陷和改进的余地。

Provider 视为 InheretedWidget 使用可以减少样板文件,事实上 Provider 是建立在 InheretedWidget 之上,它只是减少了你需要编写的代码量。

如果你的应用已经在使用 Provider,那么你可以继续使用它,这是一个非常好的状态管理包,没有理由需要迁移到另一个解决方案。

但是它还有一些改进的余地,我认为 RiverPodProvider 有改进余地的地方做得更好

RiverPod

RiverPod 的网站上可以看到,他们称自己为“Provider,但与众不同”。

这样的形容很贴切,Provider 即使削减了很多的模版,但仍然有一些是可以进一步减少的。此外Provider 依赖于 BuildContext——我认为在很多情况下这确实很棒(它会迫使你使用 Widget 树),但有时就像应用的生命周期一样,在任何的地方获取 BuildContext 是不切实际的。

RiverPodProvider 的优点上改进如下:

  • Provider 更少的样板RiverPod 在减少 Provider 模版方面做得很好,允许开发者只注册一个顶级存储而不必单独提供每个提供。(可能有人一想到把所有东西都集中在一个地方而畏缩——别担心,你可以确定你的 pod。)
  • 不依赖 BuildContext:这也是一个很好的选择,原因前面已经提到。有时你只是无法在需要的地方获得 BuildContext
  • 编译安全:到目前为止这是状态管理的最佳创新,只要代码能编译就是安全的,我们不再需要知道为什么不能在树中找到我们的 Provider , 这是一项巨大的创新,可以为你节省很多的时间。

RiverPod 只是 Provider 的不同皮肤——但是它是更光滑、更好的皮肤,如果您正在启动一个新应用并想使用 Provider ,我强烈建议你考虑 RiverPod

其他

以下是在考虑状态管理的时候调研过的方案,但最终没有使用:

  • GetX:我不是 GetX 的粉丝,GetX 试图完成很多工作,但这限制了你的灵活性,如果你希望有“完整应用场景” 的第三方包,那么 GetX 是你的最佳选择没,我对此尝试过接入,但不喜欢它。

  • get_itget_it 不是一种状态管理方案——但大家一直在使用它,如果用作状态管理方案来看,它会非常混乱。

  • redux / fish_redux / mobx:这些都来自 React,并且具有非常相似的风格——但我认为 ReactFlutter 是两个看起来相似却不同的框架,如果你习惯了它们,那么你可以使用它们,但在我看来,为 Flutter 设计的状态管理框架更为干净。