封装flutter状态管理工具示例详解
李小轰_Rex 人气:0引言
关于 Flutter 状态管理,公司项目使用的是Bloc
方案。Bloc 其实本质上是 provider
的封装扩展库,整体通过 InheritedWidget
、Notifier
外加 Stream
中转实现状态变更通知。
关于 Bloc 实现原理,有兴趣的同学可以观看这篇文章 Bloc原理解析
RxBinder
撇开Bloc
内部实现策略,小轰尝试基于数据驱动模型,自定义一套状态管理工具。构思如下:
主要成员如下:
RxBinderData
: 数据模型基类,内部封装变更通知RxBinder
: 核心类,用于关联订阅关系
代码实现
创建一个工具类用于注册和发送通知
///使用callback的形式管理通知 class RxNotifier { List<VoidCallback> _listeners = []; void addListener(VoidCallback listener) { _listeners.add(listener); } void remove(VoidCallback listener) { if (_listeners.contains(listener)) { _listeners.remove(listener); } } ///通知 void notify() { if (_listeners.isEmpty) return; for (final entry in _listeners) { entry.call(); } } }
数据模型应该具备两个特性:当数据被使用时,添加监听;当数据发生改变时发送变更通知。
///数据模型基类,(封装变更通知) class RxBinderData<T> { late T _value; late String uuid; RxNotifier subject = RxNotifier(); RxBinder? _rxBinder; RxBinderData(this._value, {RxBinder? value}) { uuid = Uuid().v4(); bindRx(value); } void bindRx(RxBinder? value) { _rxBinder = value; } @override String toString() { return value.toString(); } T get value { //添加监听,变更通知注册 _rxBinder?.register(uuid, subject); return _value; } set value(T val) { _value = val; notify(); } void notify() { //通知数据发生变更 subject.notify(); } }
创建一个中转工具类,用于统一管理数据变更时的消息分发和订阅关系
class RxBinder { Map<RxNotifier, String> _subjects = {}; ///订阅者, key是订阅的数据id, value是订阅数据发生变化时的通知回调 Map<String, List<VoidCallback>> _subscriber = {}; //注册 void register(String uuid, RxNotifier subject) { if (!_subjects.containsKey(subject)) { subject.addListener(() { _notify(uuid); }); _subjects[subject] = ''; } } //添加订阅关系 void addListener(String uuid, VoidCallback listener) { if (!_subscriber.containsKey(uuid)) { //key不存在 _subscriber[uuid] = [listener]; } else { //key已存在 List<VoidCallback> list = _subscriber[uuid]!; if (!list.contains(listener)) { list.add(listener); _subscriber[uuid] = list; } } } //通知订阅者 void _notify(String uuid) { if (_subscriber.containsKey(uuid)) { final list = _subscriber[uuid]; if (list != null && list.isNotEmpty) { for (final entry in list) { entry.call(); } } } } }
控制刷新组件
typedef WidgetCallback = Widget Function(BuildContext context); class RxBindWidget extends StatefulWidget { final WidgetCallback builder; final List<RxBinderData> binders; const RxBindWidget(this.builder, this.binders, {Key? key}) : super(key: key); @override _RxBindWidgetState createState() => _RxBindWidgetState(); } class _RxBindWidgetState extends State<RxBindWidget> { RxBinder rxBinder = RxBinder(); @override void initState() { super.initState(); for (final entity in widget.binders) { //数据源绑定Rx entity.bindRx(rxBinder); rxBinder.addListener(entity.uuid, notifyDataChange); } } void notifyDataChange() { setState(() {}); } @override Widget build(BuildContext context) { return widget.builder(context); } }
Demo 完美运行
///基础数据类型以int作为栗子 extension IntExtension on int { RxInt get rex => RxInt(this); //绑定Rx通知 void bindRx(RxBinder? value) { rex.bindRx(value); } } ///具体业务的扩展类 class RxInt extends RxBinderData<int> { RxInt(int value) : super(value); RxInt operator +(int other) { value = value + other; return this; } RxInt operator -(int other) { value = value - other; return this; } }
class Logic { RxInt count = 0.rex; void increase() => ++count; } class TestRxBinder extends StatelessWidget { final Logic logic = Logic(); TestRxBinder({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: RxBindWidget((context) { return _child(context); }, [logic.count]), ), floatingActionButton: FloatingActionButton( onPressed: () => logic.increase(), child: Icon(Icons.add), ), ); } Widget _child(BuildContext context) { return Text( '点击了 ${logic.count.value} 次', ); } }
加载全部内容