因为Obx的自动刷新,必须需要每一个变量都自带监听触发机制;所以,所有的基础类型,实体以及列表,都需要重新封装,这会造成很严重的使用影响:变量的赋值,类型标定,刷新都很正常写法有差异,不熟悉该写法的人,看了后,会很难受
因为对所有类型重新封装,经过上面的代码回溯,大家也发现,封装类型的代码相当多;封装类型占用资源肯定要比dart自带类型的大(这个问题可以避免:封装一个响应式的变量,并不一定需要很多代码,下面我给出了一个封装参考)
手搓一个状态管理框架GetX内置了俩套状态管理机制,这边也会按照其刷新机制,手搓俩套出来
我会用极其简单的代码,再现俩套经典的机制
依赖注入在做刷新机制前,首先必须写一个依赖注入的类,我们需要自己管理逻辑层的那些实例
我这边写了一个极其简单,仅实现三种基础功能:注入,获取,删除
///依赖注入,外部可将实例,注入该类中,由该类管理 class Easy { ///注入实例 static T put<T>(T dependency, {String? tag}) => _EasyInstance().put(dependency, tag: tag); ///获取注入的实例 static T find<T>({String? tag, String? key}) => _EasyInstance().find<T>(tag: tag, key: key); ///删除实例 static bool delete<T>({String? tag, String? key}) => _EasyInstance().delete<T>(tag: tag, key: key); } ///具体逻辑 class _EasyInstance { factory _EasyInstance() => _instance ??= _EasyInstance._(); static _EasyInstance? _instance; _EasyInstance._(); static final Map<String, _InstanceInfo> _single = {}; ///注入实例 T put<T>(T dependency, {String? tag}) { final key = _getKey(T, tag); //多次注入会覆盖 _single[key] = _InstanceInfo<T>(dependency); return find<T>(tag: tag); } ///获取注入的实例 T find<T>({String? tag, String? key}) { final newKey = key ?? _getKey(T, tag); var info = _single[newKey]; if (info?.value != null) { return info!.value; } else { throw '"$T" not found. You need to call "Easy.put($T())""'; } } ///删除实例 bool delete<T>({String? tag, String? key}) { final newKey = key ?? _getKey(T, tag); if (!_single.containsKey(newKey)) { print('Instance "$newKey" already removed.'); return false; } _single.remove(newKey); print('Instance "$newKey" deleted.'); return true; } String _getKey(Type type, String? name) { return name == null ? type.toString() : type.toString() + name; } } class _InstanceInfo<T> { _InstanceInfo(this.value); T value; }自定义一个监听类,这个类很重要,下面俩种机制都需要用到
///自定义个监听触发类 class EasyXNotifier { List<VoidCallback> _listeners = []; void addListener(VoidCallback listener) { _listeners.add(listener); } void removeListener(VoidCallback listener) { for (final entry in _listeners) { if (entry == listener) { _listeners.remove(entry); return; } } } void dispose() { _listeners.clear(); } void notify() { if (_listeners.isEmpty) return; for (final entry in _listeners) { try { entry.call(); } catch (e) { print(e.toString()); } } } } EasyBuilder 实现该模式需要自定义一个基类
我这地方写的极简,相关生命周期都没加,这个加起来也很容易,定义各个生命周期,在Builder控件里面触发,就可以了
为了代码简洁,这个暂且不表
class EasyXController { EasyXNotifier xNotifier = EasyXNotifier(); ///刷新控件 void update() { xNotifier.notify(); } }再来看看最核心的EasyBuilder控件:这就搞定了!
实现代码写的极其简单,希望大家思路能有所明晰
///刷新控件,自带回收机制 class EasyBuilder<T extends EasyXController> extends StatefulWidget { final Widget Function(T logic) builder; final String? tag; final bool autoRemove; const EasyBuilder({ Key? key, required this.builder, this.autoRemove = true, this.tag, }) : super(key: key); @override _EasyBuilderState<T> createState() => _EasyBuilderState<T>(); } class _EasyBuilderState<T extends EasyXController> extends State<EasyBuilder<T>> { late T controller; @override void initState() { super.initState(); controller = Easy.find<T>(tag: widget.tag); controller.xNotifier.addListener(() { if (mounted) setState(() {}); }); } @override void dispose() { if (widget.autoRemove) { Easy.delete<T>(tag: widget.tag); } controller.xNotifier.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return widget.builder(controller); } } 使用使用很简单,先看下逻辑层
class EasyXCounterLogic extends EasyXController { var count = 0; void increase() { ++count; update(); } }