界面层
class EasyXCounterPage extends StatelessWidget { final EasyXCounterLogic logic = Easy.put(EasyXCounterLogic()); @override Widget build(BuildContext context) { return BaseScaffold( appBar: AppBar(title: const Text('EasyX-自定义EasyBuilder刷新机制')), body: Center( child: EasyBuilder<EasyXCounterLogic>(builder: (logic) { return Text( '点击了 ${logic.count} 次', style: TextStyle(fontSize: 30.0), ); }), ), floatingActionButton: FloatingActionButton( onPressed: () => logic.increase(), child: Icon(Icons.add), ), ); } }效果图
Ebx:自动刷新机制自动刷新机制,因为没加泛型,所以无法确定自己内部使用了哪个注入实例,Getx中是在路由里面去回收这些实例的,但是,如果你没使用GetX的路由,又用Obx,你会发现,GetXController居然无法自动回收!!!
此处针对该场景,我会给出一种解决方案
实现在自动刷新的机制中,需要将基础类型进行封装
主要逻辑在Rx中
set value 和 get value是关键
///拓展函数 extension IntExtension on int { RxInt get ebs => RxInt(this); } extension StringExtension on String { RxString get ebs => RxString(this); } extension DoubleExtension on double { RxDouble get ebs => RxDouble(this); } extension BoolExtension on bool { RxBool get ebs => RxBool(this); } ///封装各类型 class RxInt extends Rx<int> { RxInt(int initial) : super(initial); RxInt operator +(int other) { value = value + other; return this; } RxInt operator -(int other) { value = value - other; return this; } } class RxDouble extends Rx<double> { RxDouble(double initial) : super(initial); RxDouble operator +(double other) { value = value + other; return this; } RxDouble operator -(double other) { value = value - other; return this; } } class RxString extends Rx<String> { RxString(String initial) : super(initial); } class RxBool extends Rx<bool> { RxBool(bool initial) : super(initial); } ///主体逻辑 class Rx<T> { EasyXNotifier subject = EasyXNotifier(); Rx(T initial) { _value = initial; } late T _value; bool firstRebuild = true; String get string => value.toString(); @override String toString() => value.toString(); set value(T val) { if (_value == val && !firstRebuild) return; firstRebuild = false; _value = val; subject.notify(); } T get value { if (RxEasy.proxy != null) { RxEasy.proxy!.addListener(subject); } return _value; } }需要写一个非常重要的中转类,这个也会储存响应式变量的监听对象
这个类是有着非常核心的逻辑:他将响应式变量和刷新控件关联起来了!
class RxEasy { EasyXNotifier easyXNotifier = EasyXNotifier(); Map<EasyXNotifier, String> _listenerMap = {}; bool get canUpdate => _listenerMap.isNotEmpty; static RxEasy? proxy; void addListener(EasyXNotifier notifier) { if (!_listenerMap.containsKey(notifier)) { //重要:将Ebx中的监听对象转换到此处 easyXNotifier = proxy!.easyXNotifier; //变量监听中刷新 notifier.addListener(() { //刷新ebx中添加的监听 easyXNotifier.notify(); }); //添加进入map中 _listenerMap[notifier] = ''; } } }刷新控件Ebx
typedef WidgetCallback = Widget Function(); class Ebx extends StatefulWidget { const Ebx(this.builder, {Key? key}) : super(key: key); final WidgetCallback builder; @override _EbxState createState() => _EbxState(); } class _EbxState extends State<Ebx> { RxEasy _rxEasy = RxEasy(); @override void initState() { super.initState(); _rxEasy.easyXNotifier.addListener(() { if (mounted) setState(() {}); }); } Widget get notifyChild { final observer = RxEasy.proxy; RxEasy.proxy = _rxEasy; final result = widget.builder(); if (!_rxEasy.canUpdate) { throw 'Widget lacks Rx type variables'; } RxEasy.proxy = observer; return result; } @override Widget build(BuildContext context) { return notifyChild; } @override void dispose() { _rxEasy.easyXNotifier.dispose(); super.dispose(); } }在上面说了,在自动刷新机制中,自动回收依赖实例是个蛋筒的问题,此处我写了一个回收控件,可以解决此问题
使用时,必须套一层了;如果大家有更好的思路,麻烦在评论里告知
class EasyBindWidget extends StatefulWidget { const EasyBindWidget({ Key? key, this.bind, this.tag, this.binds, this.tags, required this.child, }) : assert( binds == null || tags == null || binds.length == tags.length, 'The binds and tags arrays length should be equal\n' 'and the elements in the two arrays correspond one-to-one', ), super(key: key); final Object? bind; final String? tag; final List<Object>? binds; final List<String>? tags; final Widget child; @override _EasyBindWidgetState createState() => _EasyBindWidgetState(); } class _EasyBindWidgetState extends State<EasyBindWidget> { @override Widget build(BuildContext context) { return widget.child; } @override void dispose() { _closeController(); _closeControllers(); super.dispose(); } void _closeController() { if (widget.bind == null) { return; } var key = widget.bind.runtimeType.toString() + (widget.tag ?? ''); Easy.delete(key: key); } void _closeControllers() { if (widget.binds == null) { return; } for (var i = 0; i < widget.binds!.length; i++) { var type = widget.binds![i].runtimeType.toString(); if (widget.tags == null) { Easy.delete(key: type); } else { var key = type + (widget.tags?[i] ?? ''); Easy.delete(key: key); } } } } 使用逻辑层,这次,咱们连基类都不需要写
class EasyXEbxCounterLogic { RxInt count = 0.ebs; ///自增 void increase() => ++count; }