RxInterface 类中有个 proxy 静态变量,这个变量十分重要,他是一个中转变量!
`class _ObxState extends State<ObxWidget> { RxInterface? _observer; _ObxState() { _observer = RxNotifier(); } Widget get notifyChilds { final observer = RxInterface.proxy; RxInterface.proxy = _observer; final result = widget.build(); if (!_observer!.canUpdate) { throw """ [Get] the improper use of a GetX has been detected. You should only use GetX or Obx for the specific widget that will be updated. If you are seeing this error, you probably did not insert any observable variables into GetX/Obx or insert them outside the scope that GetX considers suitable for an update (example: GetX => HeavyWidget => variableObservable). If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX. """; } RxInterface.proxy = observer; return result; } @override Widget build(BuildContext context) => notifyChilds; } abstract class RxInterface<T> { bool get canUpdate; void addListener(GetStream<T> rxGetx); void close(); static RxInterface? proxy; StreamSubscription<T> listen(void Function(T event) onData, {Function? onError, void Function()? onDone, bool? cancelOnError}); }notifyChilds中的几行代码都有深意,一行行的解读下
final observer = RxInterface.proxy:RxInterface.proxy正常情况为空,但是,可能作为中间变量暂存对象的情况,现在暂时将他的对象取出来,存在observer变量中
RxInterface.proxy = _observer:将我们在 _ObxState类中实例化的 RxNotifier() 对象的地址,赋值给了RxInterface.proxy
注意:这里,RxInterface.proxy中 RxNotifier() 实例,有当前Obx控件的setState() 方法
final result = widget.build():这个赋值相当重要了!调用我们在外部传进的Widget
如果这个Widget中有响应式变量,那么一定会调用该变量中获取 get value
还记得get value的代码吗?
mixin RxObjectMixin<T> on NotifyManager<T> { late T _value; T get value { if (RxInterface.proxy != null) { RxInterface.proxy!.addListener(subject); } return _value; } } mixin NotifyManager<T> { GetStream<T> subject = GetStream<T>(); }
终于建立起联系了,将变量中 GetStream 实例,添加到了Obx中的 RxNotifier() 实例;RxNotifier() 实例中有一个 subject(GetStream ) 实例,Rx类型中数据变化会触发 subject 变化,最终刷新Obx
mixin NotifyManager<T> { GetStream<T> subject = GetStream<T>(); final _subscriptions = <GetStream, List<StreamSubscription>>{}; bool get canUpdate => _subscriptions.isNotEmpty; void addListener(GetStream<T> rxGetx) { if (!_subscriptions.containsKey(rxGetx)) { //重点 GetStream中listen方法是用来添加监听方法的,add的时候会刷新监听方法 final subs = rxGetx.listen((data) { if (!subject.isClosed) subject.add(data); }); final listSubscriptions = _subscriptions[rxGetx] ??= <StreamSubscription>[]; listSubscriptions.add(subs); } } }
if (!_observer!.canUpdate) {}:这个判断就很简单了,如果我们传入的Widget中没有Rx类型变量, _subscriptions数组就会为空,这个判断就会过不了
RxInterface.proxy = observer:将RxInterface.proxy中原来的值,重新赋给自己,至此 _ObxState 中的 _observer对象地址,进行了一番奇幻旅游后,结束了自己的使命
图示
总结Obx的刷新机制,还是蛮有有趣的
Rx变量改变,自动刷新包裹其变量Obx控件,其它的Obx控件并不会刷新
使用Obx控件,不需要写泛型!牛批!
但是,我认为Obx刷新机制,也是有着自身的缺陷的,从其实现原理上看,这是无法避免的