BLoC(Business Logic Component)设计模式是一个新鲜词汇, 在2018年1月的DartConf上被提出,其实是在Rx系列思想之下发展出来的响应式编程模式。
PS: 有时候从后端研发的角度来看,前端领域的一些想法确实挺前卫的。
其核心在于:将变量的变化看作一种流,并把Widget的状态绑定在流上,从而当变量改变时候,Widget接收到事件并作出响应的改变。因此BLoC可以做到完全将业务逻辑封装起来,Widget仅通过输入、输出和逻辑模块交互,做到完全的解耦。
BLoC的结构盗图一下:
BLoC的具体实现
这里的实现 90% 出自这位知乎大佬的文章,各位可以去围观一下:
在 Flutter 中使用 Bloc 来处理数据并更新 UI
流 Stream 的概念
可以把Stream看作管道,事件从一端输入,监听方从另一端获取事件并作出相应的改变。这里我们的Widget需要使用到StreamBuilder。
在Flutter中 StreamController 管理流, controller.sink 是入口, controller.stream 是出口
基本的BLoC实现
假设我们需要一个环境变量代表开和关,而App有多个页面的Switch开关控件与这个变量进行关联,我需要在任何页面拨动开关的时候,其它页面对应的开关的状态保持一致。
这里我们可以设想到的输入事件有两种:
- 变量的值改变 --> 导致开关状态变化
- 用户拨动开关 --> 导致值改变
因此会有两个Stream: 值的Stream,和用户操作事件Stream
class AppSwitchBLoC {
bool _switchValue = false;
StreamController<bool> _appSwitchController = StreamControler();
// 用于值改变事件的输入(私有变量,不暴露出来)
StreamSink<bool> get _inSwitch = _appSwitchController.sink;
// 用于值改变事件的输入(值的输出暴露出来)
Stream<bool> get outSwitchValue = _appSwitchController.stream;
StreamController _switchActionController = StreamController();
// 用户输入触发(暴露出来)
StreamSink get changeSwitchValue = _switchActionController.sink;
AppSwitchBLoC() {
// 指定_handleEvent函数处理用户的输入事件
_switchActionController.stream.listen(_handleEvent);
}
_handleEvent(