作者:Matt Carroll
原文:https://medium.com/fluttery/understanding-state-management-and-why-you-never-will-dd84b624d0e
译者:鲍博
所有相关权利属于原文作者,转载请保留原文信息。欢迎反馈翻译问题。以下均为翻译。

本文来自作者的个人视角,不代表Flutter团队或Google公司的立场。

状态管理是Flutter社区的热门话题

Better state management solution · Issue #11093 · flutter/flutter​github.com
f421dfca9bb2e263d894b538ee7bf5b2.png
State management​flutter.io
eda2175f8cc55af63de2d90f7bc9bbe1.png
State Management the Flutter Way​flutterbyexample.com
fdf36465d90fb52c35b40ccc6bbb1d5e.png
https://medium.com/flutter-community/let-me-help-you-to-understand-and-choose-a-state-management-solution-for-your-app-9ffeac834ee3​medium.comhttps://proandroiddev.com/you-might-not-need-redux-the-flutter-edition-9c11eba006d7​proandroiddev.comRedBrogdon/rebloc​github.com
9973bb5689248b7d7df48c0460abbab8.png

还有更多……

为什么这个话题这么受欢迎?为什么似乎每个人都在疑惑这个问题?为什么如此多的开发者渴求“状态管理”的方案?

让我们从头开始。

什么是状态?

如果请100个开发者定义“状态”,会得到很多种回答:

  • 数据(无论数据在这里指什么)。
  • 所有StatefulWidgets里面的所有变量。
  • 整个程序里面的所有变量。
  • 一个Store,比如,Redux Store或者Flux Store。
  • 应用在某个特定时间的行为。(我的定义)

什么是状态管理?

如果请100个开发者定义“状态管理”,会得到很多种回答:

  • 类似Redux或者Flux或者BLoC的东西。(总会有开发者认为,举例就等于定义概念)
  • 数据怎样进出一个store。
  • 信息怎样在一个系统内部流通。
  • 业务逻辑怎样与用户界面交互。
  • 数据库。
  • 六边形架构。
  • 谁知道呢。(我的定义)

你混淆了很多概念!

关于“状态管理”的争论体现了定义对于词语的重要性。状态管理这个概念,是由很多相互独立的行为堆砌在一起所构成的不良定义:

  • 数据持久化
  • 信息流
  • 编程范式
  • I/O(尤其是网络和缓存)
  • 应用架构
  • 表现行为
  • UI生成
  • 等等

你会发现上面这些行为不存在普适的解决方案。你绝对无法找到对上面这些行为普适的解决方案。而且这是好事,因为如果这样的普适方案存在,你作为软件开发者的职业就不会存在了。

人们想要一个解决“状态管理”的方案,听起来很简单,但实际上抽象状态就等于抽象“软件工程”。这就是为什么每个方案看起来都难以解释地杂乱。https://twitter.com/flttry/status/1089785672167174144

据我所知,“状态管理”是笼统的叫法,它实际上的意思是“软件工程”。这样,我们看到开发者提问“我怎样管理状态?”或者“Flutter中怎样进行状态管理”的时候,其实他在问的是“我怎样设计软件?”我无法回答,我需要多少年的时间才能回答完这个问题?!

高效交流,以获得你的问题的答案

如果你关于怎样“管理状态”的提问得到了不太令人满意的回应,那是因为没人知道你的意图是什么。

如果你想知道怎样进行网络请求并缓存结果,就问这个。

如果你想在你的应用中放置Redux风格的store,就问这个。

如果你想了解怎样在一个Flutter widget层级中填充信息,就问这个。

如果你想知道其他人怎样设计他们业务中的规则和关系并把这些跟Flutter widget层级联系起来,就问这个。

如果你想了解使用硬件例如声音、加速度传感器或者蓝牙的各种方法,就问这个。

找到问题的根源是你的重要一步。如果在问题中不使用“管理”和“状态”这样的词,你会怎样描述同一个问题?

不要低估业务

从大局来说,记住你编写代码的目的是产出某种产品或者服务。产品的类型可能是:

  • 通信
  • 金融
  • 运输
  • 影音娱乐
  • 社交网络
  • 等等

这些分类之所以存在,是因为每一类产品代表着独特的价值主张,目标受众是独特的用户群,提供独特的功能特性,满足独特的需求,可能还支持着独特的技术。

开发者提出问题的时候很少会考虑到所在的业务,开发者回答问题的时候也一样。这意味着社交网络的开发者可能会套用为运输行业所设计的软件架构。泛泛而谈的话,这样做像是合理的吗?

牢记你在为你的公司,你的产品和你的顾客做事。比起要不要在应用中加入一个Redux store,解决产品、公司和行业之间的业务规则和联系要重要得多!

与Flutter一起前进

想要解决误会和困惑,仅仅指出这些误会和困惑是不够的,所以让我们讨论一下可能会让你更容易解决“状态管理”这个泥泞问题的方法。

了解Flutter的边界

在我的Flutter相关演讲中,我总是强调:Flutter不是一个应用框架,它是一个可移植的UI工具组合。

Flutter vs Web with Matt Carroll​www.youtube.com

在Flutter中,你创建用户界面,而不是应用特性。因此,了解Flutter的职责在哪里结束以及你的应用在哪里开始,是关键。

Flutter的主要组成部分是一个widget树,不过如此。Flutter带有与Java/Kotlin/Obj-C/Swift交流的方法,不过这只是Flutter使用Dart实现所带来的副作用——这些通信方法并不是Flutter基础功能的一部分。

当你想使用Flutter实现一个视图或者应用的时候,你显示一个Flutter widget树。通过Flutter提供的接口,你在这个树上组合现有的widget、在这个树上创建并组合自定义的widget、通过重新构建这个树来改变屏幕上的像素,这些差不多就是Flutter的全部职责。在widget树之外,你应该完成你的应用所需要的任何其他工作。

这个概述所留下的一个问题是,开发者应该怎样把信息放进这个树,以及怎样从这个树里取回交互信息。很幸运,Flutter在自己职责的边界上提供了一些能帮到你的工具。

学习Flutter边界上的工具

为了向Flutter widget树注入数据,开发者自然可以把数据提供给顶层widget,然后在widget层级中一层层地传递下去。然而,这个方法较为冗长、容易搞砸而且可能为本来独立的概念带来不必要的耦合。

InheritedWidget是一个由Flutter提供,帮助开发者为widget树注入数据的工具。InheritedWidget允许树中较低层次的widget向上查找,获得祖先widget的引用,以及在祖先改变的时候重建自身。Theme.of()和Navigator.of()都是InheritedWidget的例子。

InheritedModel是InheritedWidget的一个变体,但InheritedModel允许组件只有在数据的一部分改变的时候才会重建。这样做的意义是实现性能上的优化。

StreamBuilder是一个可以放进组件树的组件,它在传入的stream里出现新对象的时候重建它自身。

如果想自widget树中获得交互信息,你通常应该从GestureDetector、按钮、输入框或者其他接受用户交互的widget入手。这可以提供那些会引发你的代码中行为的事件。所有这些widget都接受由你提供的、包含任意逻辑的回调函数。

在回调函数中,你可以调用保存在widget里面的对象上的方法,或者获取一个单例对象并调用上面的方法,或者通过(上面提到的)InheritedWidget获取到对象并调用上面的方法。无论你选择哪种方式,步骤倾向于是一样的:

  1. 为用户输入注册回调函数。
  2. 回调函数被Flutter调用。
  3. 获得一个保存了你的应用行为的Dart对象。
  4. 在这个对象上调用你想用来响应用户输入的相应方法。

通过这些Flutter边界上供你差遣的工具,你可以自己决定使用Redux、BLoC、数据模型、领域模型、六边形架构或者完全自定义的方案了。

了解为什么存在Redux和BLoC

开发者们很容易加入到Redux和BLoC的流行潮流中,这些方案有着病毒式的增长速度。就像每一次流行潮流中的方案一样,这些方案没有什么根本上的错误。问题在于开发者选择使用这些方案之前进行的决策过程(或者说缺乏决策过程)。

你知道Redux在一开始仅仅是在JavaScript中实现时间旅行的一个方法吗?

Dan Abramov - The Redux Journey at react-europe 2016​www.youtube.com

当然,今天的Redux不仅仅是一个实验品,但它所在的历史和场景也值得考虑。

那么BLoC呢?

Googled的AdWords团队希望在他们的移动应用中使用Flutter。这个团队还希望新应用能与他们的AngularDart web应用共享业务逻辑。AdWords团队创造了业务逻辑组件的概念(BLoC)来解决他们的问题,并在2018年早期公开了这一设计。

Flutter / AngularDart – Code sharing, better together (DartConf 2018)​www.youtube.com

2018年晚些时候,Flutter开发者关系团队的Matt和Filip希望为Flutter开发者们提供一些为Flutter widget树增加业务逻辑的灵感。Matt和Pilip查阅了Google内部的各个团队解决这一问题的方法并注意到了BLoC。他们随后在I/O 2018上介绍了BLoC,作为开发者连接业务逻辑和Flutter widget树的案例。

Build reactive mobile apps with Flutter (Google I/O '18)​www.youtube.com

这个模式不是斯坦福的什么实验室的严格科研成果,也不是Flutter内嵌的。BLoC只是很多种方案中的一种,它在Google的重要活动上被介绍这件事似乎让它成为了某种官方推荐给所有人的“数据管理方案”,但现在你了解情况了!

所以,只管选择你想要的。Redux、BLoC、数据模型、领域模型、六边形架构等等。但是,要确定你自己了解自己为什么选择自己所使用的方案,同时了解Flutter的职责在哪里结束而你的应用的职责在哪里开始。所有关于“状态管理”的问题背后真正的问题是,开发者对Flutter的widget树不够了解而无法自己找到答案。当你真正能得心应手地与Flutter widget树进行数据交互的时候,这个问题变得乏味又无意义。你甚至会疑惑自己当时为什么要提这个问题。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐