- 为什么需要状态管理
- provider
- bloc
- redux
- 对比
- 总结
为什么需要状态管理
在了解和进行Flutter状态管理框架对比之前呢,我们先来问自己一个问题:为什么需要状态管理?
如果我们的应用足够简单,Flutter作为一个声明式框架,我们或许只需要将数据映射成视图就可以了。我们可能并不需要状态管理,就像下面这张图:
但是随着功能的增加,我们的应用程序将会有几十个甚至上百个状态。这个时候我们的应用将会变成这样:
在这种情况下我们很难再清楚的测试维护我们的状态,因为它看上去实在是太复杂了!而且还会有多个页面共享同一个状态。这个时候如果想在详情页改变一个模型的状态比如点赞收藏,在返回到列表时能够及时更新这个状态,在默认情况下是很难实现的。
整个问题出在Flutter为我们提供的状态管理方式:StatefulWidget。因为State 属于某一个特定的 Widget,在多个 Widget 之间进行交流的时候,虽然你可以使用callback 解决,但是当嵌套足够深的话,那么将进入callback传递的地狱。
这时候,我们便迫切的需要一个架构来帮助我们理清这些关系,并且轻松实现状态的管理和共享,这个时候我们就需要用到状态管理框了。
provider
provider是基于InheritedWidget的包装,通过使用provider而不是手动编写InheritedWidget就可以实现页面和其子页面间的数据共享。
provider是Flutter Favorite中的插件之一,也是目前
Flutter官方推荐和使用最多的状态管理框架。
provider提供的主要功能有:
- 简化的资源分配与处置
- 懒加载
- 相较于每次创建一个新类,大大减少模板代码量
- 对开发者工具更为友好
- 更通用的消费 InheritedWidget 的方式(见 Provider.of/Consumer/Selector )
- 提升类的可伸缩性,整体的监听架构(listening mechanism)时间复杂度以指数级增长(如ChangeNotifier, 其复杂度为O(N²))
建议之前还没接触过
provider
小伙伴,可以通过Flutter官网的这个simple以及官方文API说明来练习下对provider的使用,以方便后面课程的学习。
bloc
BLoC全称(Business Logic Component)是谷歌提出的一种设计模式,利用流的方式实现界面的异步渲染和重绘,我们可以非常快速的通过BLoC实现业务与界面的分离。
BLoC只是一种设计模式,不包含任何代码,所以要在Flutter中实现BLoC设计模式需要借助flutter_bloc这个库来完成。
flutter_bloc
是一个可预测的状态管理库,可帮助我们实现BLoC(业务逻辑组件)设计模式。
BLoC设计模式有助于将UI与业务逻辑分开。遵循BLoC模式有利于项目的可测试性和可重用性。在BLoC中有个非常重要的概念:Cubit
。
Cubit
Cubit是Bloc的基础(也可以说是Bloc基于Cubit)。Cubit是一种特殊类型Stream,可以扩展以及管理任何类型的状态。Cubit需要一个初始状态,该状态将是emit被调用之前的状态。cubit
的当前状态可以通过state
来获取,并且可以通过emit
来生成一个新的state
来达到更新cubit
状态的目的:
cubit状态更改始于预定义的函数调用,这些函数可以使用该emit方法输出新状态。onChange在每个状态更改时调用,并包含当前状态和下一个状态。
对
bloc
设计模式感兴趣的小伙伴可以通过flutter_bloc的example获取具体的用例。
Redux
接下来我们说说Redux,说到Redux 前端小伙伴一定都不陌生,Redux 是 JavaScript 状态容器,提供可预测化的状态管理,可以让你构建一致化的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。
Redux最为关键的就是它的数据流了:
redux数据流:
- 用户(操作View)发出Action,发出方式就用到了dispatch方法;
- 然后,Store自动调用Reducer,并且传入两个参数(当前State和收到的Action),Reducer会返回新的State,如果有Middleware,Store会将当前State和收到的Action传递给Middleware,Middleware会调用Reducer 然后返回新的State;
- State一旦有变化,Store就会调用监听函数,来更新View;
到这儿为止,一次用户交互流程结束。可以看到,在整个流程中数据都是单向流动的。
与其说Redux是一个框架倒不如说Redux是一个设计思想,Redux在不同语言和框架中有不同的实现,比如在react-native可以借助中有react-redux来实现Redux。在Flutter中如果想使用Redux可以借助flutter_redux来完成。
总结
框架/方案 | 优点 | 缺点 | 使用建议 |
setState | 无需引入依赖、使用简单 | 不支持页面间数据共享 | 适用于较小规模项目的状态基础管理方法 |
provider | 基于InheritedWidget、简洁易用、Flutter官方推荐 | 只能实现页面和其子页面间的状态共享 | 中大型项目首选方案 |
bloc | 能够很好地实现业务逻辑的复用以及视图与业务逻辑的分离 | 使用上结构相对复杂 | 在Flutter中除provider外,另一个不错的状态管理方案 |
redux | 受众广、其它语言或框架也都有实现 | 概念较多比较难理解 | 如果之前使用过Redux并且不想引入provider的情况下 |