【源码篇】Flutter GetX深度剖析 | 我们终将走出自己的路(万字图文) (8)

_ObxState 中代码就是核心代码了

class Obx extends ObxWidget { final WidgetCallback builder; const Obx(this.builder); @override Widget build() => builder(); } abstract class ObxWidget extends StatefulWidget { const ObxWidget({Key? key}) : super(key: key); @override _ObxState createState() => _ObxState(); @protected Widget build(); } class _ObxState extends State<ObxWidget> { RxInterface? _observer; late StreamSubscription subs; _ObxState() { _observer = RxNotifier(); } @override void initState() { subs = _observer!.listen(_updateTree, cancelOnError: false); super.initState(); } void _updateTree(_) { if (mounted) { setState(() {}); } } @override void dispose() { subs.cancel(); _observer!.close(); super.dispose(); } 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; } 添加监听

一个控件想刷新,肯定有添加监听的逻辑,再在某个地方手动触发

看下_ObxState类在哪添加监听:只展示监听添加的代码

_ObxState初始化的时候,会实例化一个 RxNotifier() 对象,使用 _observer变量接受:这个操作很重要

initState中做了一个比较关键的操作,_observer的listener方法中,将 _updateTree方法传进去了,这个方法中的逻辑体就是 setState()

class _ObxState extends State<ObxWidget> { RxInterface? _observer; late StreamSubscription subs; _ObxState() { _observer = RxNotifier(); } @override void initState() { subs = _observer!.listen(_updateTree, cancelOnError: false); super.initState(); } void _updateTree(_) { if (mounted) { setState(() {}); } } }

上述很多逻辑和 RxNotifier 类相关,来看下这个类

RxNotifier 这个类,内部会实例一个 GetStream() 对象,然后赋值给 subject

上面赋值 _updateTree 方法被传入的 GetStream() 类中,最终添加 _onData 该列表变量中

瞟一眼 _notifyData方法,是不是遍历执行了 _onData 列表中item的方法( item. _data?.call(data) )

class RxNotifier<T> = RxInterface<T> with NotifyManager<T>; mixin NotifyManager<T> { GetStream<T> subject = GetStream<T>(); final _subscriptions = <GetStream, List<StreamSubscription>>{}; bool get canUpdate => _subscriptions.isNotEmpty; StreamSubscription<T> listen( void Function(T) onData, { Function? onError, void Function()? onDone, bool? cancelOnError, }) => subject.listen( onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError ?? false, ); } class GetStream<T> { void Function()? onListen; void Function()? onPause; void Function()? onResume; FutureOr<void> Function()? onCancel; GetStream({this.onListen, this.onPause, this.onResume, this.onCancel}); List<LightSubscription<T>>? _onData = <LightSubscription<T>>[]; FutureOr<void> addSubscription(LightSubscription<T> subs) async { if (!_isBusy!) { return _onData!.add(subs); } else { await Future.delayed(Duration.zero); return _onData!.add(subs); } } int? get length => _onData?.length; bool get hasListeners => _onData!.isNotEmpty; void _notifyData(T data) { _isBusy = true; for (final item in _onData!) { if (!item.isPaused) { item._data?.call(data); } } _isBusy = false; } LightSubscription<T> listen(void Function(T event) onData, {Function? onError, void Function()? onDone, bool? cancelOnError}) { final subs = LightSubscription<T>( removeSubscription, onPause: onPause, onResume: onResume, onCancel: onCancel, ) ..onData(onData) ..onError(onError) ..onDone(onDone) ..cancelOnError = cancelOnError; addSubscription(subs); onListen?.call(); return subs; } }

上面代码流程有一点绕,下面画了一个图,希望对各位有所帮助

Obx监听添加

监听转移

在_ObxState类中做了一个很重要,监听对象转移的操作

_observer中的对象已经拿到了Obx控件内部的setState方法,现在需要将它转移出去啦!

下面贴下将 _observer 中对象转移出去的代码:主要的逻辑就是在 notifyChilds 方法中

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgyyyj.html