GetX状态管理的实现机制原理剖析

1,838 阅读16分钟

前言

GetX 在网上已经有了很多优秀的文章,看完之后总觉得不尽兴,所以提笔自己写了一篇,也为之后公司内部分享提供素材,这篇文章我就打算只讲 GetX 状态管理是如何实现的,我文笔不好,写的不一定通俗易懂,所以这里也有一个视频版本,是我和我同事在周末分享的时候录制的,如果这篇文章没有帮助到大家呢也可以去看 GetX 状态管理 GetBuilder 以及 Obx 的实现原理 ,希望我做的视频版本也可以帮助到大家,本篇文章基于 get: 4.6.5,下面跟随我的脚步,一起去看 GetX 源码,我下面所说的控制器对象都是 GetxController 哈。

依赖注入实现

在使用Getx的时候有一个非常方便的地方,我们开发人员只需要确保你的控制器对象已经被执行了 Get.put(SimpleController()) 操作,那么在项目中的任何一个角落都可以通过 find 操作来使用 SimpleController ,在开发过程中 GetxController 通常承担着维护生命周期以及定义我们的开发逻辑,比如说网络请求,所以 GetxController 在被持久化之后(虽然网上都叫依赖注入,但我觉得叫持久化更贴切点),我们就可以在较深的 Widget 层级之下拿到这个 SimpleController 对象然后调用里面函数或者自己入参传递数据给上层控件,既然是拿那必然就有存的操作,这里的拿就是 find 操作,存也就是 put 操作。

如何去把 GetxController 对象持久化 - 执行 put 操作

put 操作想必大家都知道就是执行下面的这一行代码 final controller = Get.put(SimpleGetBuilderController()); ,执行完毕之后你的 SimpleGetBuilderController 就被持久化了,看到这个 put 是不是联想到了 Map ,GetX 的源码里就是通过 Map 来缓存这些控制器对象的。

///1、Get.put
S put<S>(S dependency,
        {String? tag,
        bool permanent = false,
        InstanceBuilderCallback<S>? builder}) =>
    GetInstance().put<S>(dependency, tag: tag, permanent: permanent);

///2 GetInstance().put
S put<S>(
  S dependency, {
  String? tag,
  bool permanent = false,
  @deprecated InstanceBuilderCallback<S>? builder,
}) {
  _insert(
      isSingleton: true,
      name: tag,
      permanent: permanent,
      builder: builder ?? (() => dependency));
  return find<S>(tag: tag);
}
  • 执行 Get.put 操作最终还是把任务交给了 GetInstance 去处理,之里🈶️两个比较重要的入参 dependency 和 tag , dependency 表示传递过来的控制器对象,而 tag 用于区分相同页面不同控制器对象,主要还是用在生成 key 的时候,这个我在后面会讲。

  • GetInstance().put 操作中最终会执行 _insert 函数,_insert 函数内部才是真正执行插入控制器的操作,返回值是通过 find<S>(tag: tag); 来获取的,这个我在后面讲,现在重点关注 _insert

void _insert<S>({
  bool? isSingleton,
  String? name,
  bool permanent = false,
  required InstanceBuilderCallback<S> builder,
  bool fenix = false,
}) {
  ///1 key 已经生成 1、类的类型名称字符串 2、类的类型名称字符串+tag
  final key = _getKey(S, name);
  
  if (_singl.containsKey(key)) {
    final dep = _singl[key];///根据key获取控制器对象 - (_InstanceBuilderFactory)
    ///tag01
    if (dep != null && dep.isDirty) {
      _singl[key] = _InstanceBuilderFactory<S>(
        isSingleton,
        builder,
        permanent,
        false,
        fenix,
        name,
        lateRemove: dep as _InstanceBuilderFactory<S>,
      );
    }
  } else {
    _singl[key] = _InstanceBuilderFactory<S>(
      isSingleton,
      builder,
      permanent,
      false,
      fenix,
      name,
    );
  }
}
  • _getKey 函数内部非常简单就是执行了一行代码name == null ? type.toString() : type.toString() + name;name表示在 put 操作的时候传递过来的 tag 而 type 是我们开发人员自己定义的控制器 type 类型,根据这两个参数来拼凑出一个 key

  • 如果 _singl 集合中已经包含了这个 key 说明控制器对象已经被持久化了,我们从 _singl 中获取这个控制器对象赋值给字段 dep

  • 在 tag01 中有个有意思的字段 isDirty ,该字段表示是否被标记为等待销毁,如果 dep 不为 null 并且 isDirty 为 true 那么会重新创建一个 _InstanceBuilderFactory 并保存到 _singl 中,这里注意下 _singl 中维护的都是 _InstanceBuilderFactory(封装了控制器对象),同时将之前的 dep 维护到 lateRemove 字段中

  • isDirty 这个字段默认为false,为了搞清楚它在哪里被赋予为true的,我全局搜索了下发现在 markAsDirty 这个函数中会被赋值为 true ,而 markAsDirty 会在 reportRouteWillDispose 函数中被调用即路由被销毁的时候被调用也就是 didReplace 和 didRemove 中被执行

  • 如果在第一步中我们没有找到这个 key 那么就很简单啦,直接 new 一个 _InstanceBuilderFactory 添加到 _singl 集合中就可以了

怎么样获取 GetxController 对象

S find<S>({String? tag}) {
  final key = _getKey(S, tag);
  if (isRegistered<S>(tag: tag)) {
    final dep = _singl[key];
    if (dep == null) {
      if (tag == null) {
        throw 'Class "$S" is not registered';
      } else {
        throw 'Class "$S" with tag "$tag" is not registered';
      }
    }
    final i = _initDependencies<S>(name: tag);
    return i ?? dep.getDependency() as S;
  } else {
    throw '"$S" not found. You need to call "Get.put($S())" or "Get.lazyPut(()=>$S())"';
  }
}
  • 通过 find 函数来获取 GetxController 对象,通常我们在代码中可以通过这种写法Get.find<SimpleGetBuilderController>();

  • find 操作的本质就是从 _singl 集合中获取一个 _InstanceBuilderFactory 对象,所以通过 _getKey 来生成一个 key 值,在 isRegistered 中判断 _singl 是否包含这个 key ,如果没有的话直接抛异常提示需要去执行 put 的操作

  • _singl 集合中如果没有查找到对应的 _InstanceBuilderFactory 同样会会抛异常,这里有个非常重要的函数 _initDependencies<S>(name: tag);该函数会在内部执行 _startController ,也就是 GetxController 生命周期函数 onStart 被执行的时机,我就不展开说了,后面会去补充一篇文章介绍 GetxController 生命周期函数被执行的时机

  • 执行 return i ?? dep.getDependency() as S; 也就是最终获取到的 GetxController 对象

GetBuilder 实现原理

GetBuilder 如何添加监听

通常使用 GetBuilder 与 update 两者配合实现界面的刷新,在需要刷新的 Widget 外层包裹一个 GetBuilder 既可实现这个需求,update 通知所有的 GetBuilder 来实现刷新的功能,所以我们可以判断出这里最起码有个添加监听的操作,第一步我们关注下 GetBuilder 是如何实现的,GetBuilder 是一个 StatefulWidget ,所以我们看下 GetBuilderState 的 initState 函数。

void initState() {
  // _GetBuilderState._currentState = this;
  super.initState();
  widget.initState?.call(this);
  //调用 isRegistered 来判断是否已经注册这个控制器(即是否在Map集合中保存了这个控制器对象)
  var isRegistered = GetInstance().isRegistered<T>(tag: widget.tag);
  //tag01
  if (widget.global) {
    if (isRegistered) {
      if (GetInstance().isPrepared<T>(tag: widget.tag)) {
        _isCreator = true;
      } else {
        _isCreator = false;
      }
      controller = GetInstance().find<T>(tag: widget.tag);
    } else {
      controller = widget.init;
      _isCreator = true;
      GetInstance().put<T>(controller!, tag: widget.tag);
    }
  } else {
     //tag02
    controller = widget.init;
    _isCreator = true;
    controller?.onStart();
  }

  if (widget.filter != null) {
    _filter = widget.filter!(controller!);
  }
    //tag03
  _subscribeToController();
}
  • global 值默认是 true ,表示是否是全局的,通过 GetInstance().isRegistered 来判断该控制器对象是否已经被添加到 _singl 集合中,如果已经被添加则 _isCreator 标志为 true 表示控制器对象已经被创建成功,如果没有被添加则从 init 参数中获取 Controller 对象,如果你用过 GetX 那么在定义 GetBuilder 的时候肯定知道有个 init 入参,这个入参也是用来定义传递 Controller 对象,同时紧接着执行 GetInstance().put<T>(controller!, tag: widget.tag);将 Controller 对象注册到 _singl 中,所以 GetX 定义 global 参数的目的我想就是为了确保你的 Controller 对象在被持久化之后可以在项目的任何一个角落里可以获取到。

  • 如果 global 被人为的定义为了 false ,那么还是老老实实的从 init 中获取,同时执行 onStart 函数也就是 GetxController 的第一个生命周期函数。

  • _subscribeToController() 我们需要关注的最重要的函数即添加监听操作

void _subscribeToController() {
  _remove?.call();
  //如果 id 为 null 执行 addListener 函数,我们发现这里会添加一个 getUpdate ,
  //这个 _filter 没啥用我们不管。
  //id的作用是为了定点刷新,如果在 GetBuilder 中定义了 id 那么我们可以通过在 update 中
  //传入这个 id 来实现刷新定义了相同 id 的 GetBuilder
  //addListener 和 addListenerId 它们逻辑差不多,我们重点关注 addListener 后面的操作
  _remove = (widget.id == null)
      ? controller?.addListener(
          _filter != null ? _filterUpdate : getUpdate,
        )
      : controller?.addListenerId(
          widget.id,
          _filter != null ? _filterUpdate : getUpdate,
        );
}

//GetxController 混入了 ListNotifierMixin
//ListNotifierMixin 中定义了一个集合 _updaters
//所以这里我们发现 addListener 操作就是将 getUpdate 添加到 _updaters 中
@override
Disposer addListener(GetStateUpdate listener) {
  assert(_debugAssertNotDisposed());
  _updaters!.add(listener);
  return () => _updaters!.remove(listener);
}

//getUpdate 函数封装了 setState 操作
//到这一步是不是有种豁然开朗的感觉,原来GetX的内部也是通过 setState 来实现界面刷新的
//总结下:
//1、GetBuilder 的作用之一就是用来添加监听
//2、有多少 GetBuilder 就会有多少 getUpdate 被添加到 _updaters 集合中
void getUpdate() {
  if (mounted) setState(() {});
}

update 函数的实现原理

void update([List<Object>? ids, bool condition = true]) {
//tag01
  if (!condition) {
    return;
  }
  if (ids == null) {
    //tag01
    refresh();
  } else {
  //tag02
    for (final id in ids) {
      refreshGroup(id);
    }
  }
}

void refresh() {
  _notifyUpdate();
}

void _notifyUpdate() {
  for (var element in _updaters!) {
    element!();
  }
}
  • update 函数非常的简单,ids 表示你需要刷新的对应 id 的 GetBuilder ,condition 表示是否需要刷新,如果 ids 为 null 则执行 refresh 函数刷新所有的 GetBuilder,refresh 函数中会执行 _notifyUpdate() ,也就是在 _notifyUpdate 中会遍历 _updaters 集合并执行 _updaters 里的方法,_updaters 大家应该很熟悉了在 GetBuilder 中的 _subscribeToController 函数中会执行添加监听的操作,可以回过头看 “GetBuilder如何添加监听”,添加的监听函数就是 setState ,所以说 setState 就是在这里被执行的,执行 update 就是执行所有封装在 _updaters 中的 setState

  • refreshGroup 也是一样的逻辑,只是添加监听的操作换成了 addListenerId ,而遍历的对象成了 _updatersGroupIds 而已

Obx 实现原理

Obx 实现原理实在可以说是难懂,我能把它看下来我自己都觉得是一个奇迹,所以接下来的第一步我们先去关注它的继承结构,然后在慢慢抽丝剥茧般的往下走,obx 的用法我就不说了,先看这行代码 var count = 0.obs; 这样就实现了一个最简单的可以观察的值,可以确定的是这里肯定是用了扩展函数。

extension IntExtension on int {
  RxInt get obs => RxInt(this);
}

这里是对 int 进行了一次扩展,所以 0.obs 你也可以写成 RxInt(0) ,继续点击下去跟随源码,RxInt 继承自 Rx , 并且里面重写了操作符,

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;
  }
}

Rx 这个类没什么好说的里面没有什么代码,我就快刀斩乱麻般的把后面的继承结构给Copy下来,多余的代码都会删除

class Rx<T> extends _RxImpl<T> {
  Rx(T initial) : super(initial);
///省略代码
}

///这里我们重点关注 RxNotifier 和 RxObjectMixin
abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T>{
///省略代码
}

///RxNotifier其实就是 RxInterface 混入了 NotifyManager
class RxNotifier<T> = RxInterface<T> with NotifyManager<T>;

///同样 RxObjectMixin 也混入了 NotifyManager
mixin RxObjectMixin<T> on NotifyManager<T> {
    ///这里的代码我们只关注 set value 和 get value
    set value(T val) {
      if (subject.isClosed) return;
      sentToStream = false;
      if (_value == val && !firstRebuild) return;
      firstRebuild = false;
      _value = val;
      sentToStream = true;
      subject.add(_value);///执行 Rx 的 GetStream 的 add 操作,而这个操作在Obx中已经封装好了
    }

    /// Returns the current [value]
    T get value {///这里的 RxInterface.proxy 其实就是 Obx 中实例化的 RxNotifier
      RxInterface.proxy?.addListener(subject);///调用 Obx 中的 RxNotifier.addListener ,将变量中的 GetStream 添加到 Obx 中
      return _value;///返回默认值
    }
}

  • 我们通过上面的代码可以看出 0.obx 本质上就是一个 RxInt 类

  • 目前我们仅仅只是定义了这个 RxInt 类,还没做任何操作,RxObjectMixin 中的 get 和 set value 现在还没开始调用,你在执行自增操作的时候会执行 set value ,在你的控件第一次被 build 的时候会执行 get value ,现在我们暂时不关注这些,先脑海中有个印象把它的继承给记住,不然后面就懵逼了

///NotifyManager 是一个非常重要的类,这里初始化了一个 GetStream 对象
///由于目前我们看的继承结构都是从 RxInt 这里开始的,所以从 RxInt 流程中
///初始化的 GetStream 下面我们统称为 Rx的GetStream
mixin NotifyManager<T> {
  GetStream<T> subject = GetStream<T>();
  final _subscriptions = <GetStream, List<StreamSubscription>>{};

  bool get canUpdate => _subscriptions.isNotEmpty;

  /// This is an internal method.
  /// Subscribe to changes on the inner stream.
  void addListener(GetStream<T> rxGetx) { ///getValue操作实际上也就是添加一个监听
    if (!_subscriptions.containsKey(rxGetx)) {
      final subs = rxGetx.listen((data) {///每次执行Rx的set操作的时候都会执行这里传入的回调
        if (!subject.isClosed) subject.add(data);///执行Obx中的GetStream对象的add操作刷新界面
      });///rxGetx.listen 你会发现这里只有一个入参,这个入参数就是 onData ,所以这个 onData 是封装到了 Rx 的 GetStream 中的_onData集合中的,
      final listSubscriptions =                                                  ///在 set 操作的时候会遍历这个集合并执行这个onData
          _subscriptions[rxGetx] ??= <StreamSubscription>[];                      ///也就是说这时候会执行 if (!subject.isClosed) subject.add(data);
      listSubscriptions.add(subs);
    }
  }

  StreamSubscription<T> listen(
    void Function(T) onData, {
    Function? onError,
    void Function()? onDone,
    bool? cancelOnError,
  }) =>
      subject.listen(
        onData,
        onError: onError,
        onDone: onDone,
        cancelOnError: cancelOnError ?? false,
      );

}

我们总结下当我们写了这样的一行代码的时候 var count = RxInt(0); 我们可以获取到一个 Rx的GetStream对象,并且初始化了一个 RxInt 对象,我们还得知了get value 和 set value 的操作只是目前还没执行到它们,有一个非常重要的混入类 NotifyManager ,在它的内部有一个 addListener 的操作,所以必然在某一个地方会执行 addListener ,只是现在暂时不知道,不急,慢慢看,obx 里面还有另一个包裹在你需要执行状态管理的Widget外层,也就是一个 Obx Widget,接下来我们跟着它的节奏去看。

///Obx 是一个Widget,下面的代码中发现了 controller.count.value
///也就是 get value 的操作,看样子有个切入点了
Obx(
  () => Text(
    '${controller.count.value}',
    style: const TextStyle(
      fontSize: 30,
      color: Colors.black,
    ),
  ),
),

///Obx本质上就是一个 ObxWidget,ObxWidget 是一个 StatefulWidget
///所以接下来重点看 _ObxState
class Obx extends ObxWidget {
  final WidgetCallback builder;

  const Obx(this.builder);

  @override
  Widget build() => builder();
}

class _ObxState extends State<ObxWidget> {
  final _observer = RxNotifier(); ///tag01 - _ObxState 中初始化了一个 RxNotifier 对象
  late StreamSubscription subs;

  @override
  void initState() {
    super.initState();
    subs = _observer.listen(_updateTree, cancelOnError: false);///tag02 - _updateTree中封装了 setState 函数,
  }                                                            ///执行 RxNotifier 的 listen 函数最终会执行 "Obx 的" GetStream 的 listen 函数
  ///最终执行刷新界面的函数                                        ///将 _updateTree 封装到 LightSubscription 中添加到 _onData 集合中维护起来
  void _updateTree(_) {
    if (mounted) {
      setState(() {});
    }
  }

  @override
  void dispose() {
    subs.cancel();
    _observer.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) =>
      RxInterface.notifyChildren(_observer, widget.build);///tag03 - 传入Obx的 RxNotifier
}

///RxNotifier#listen
StreamSubscription<T> listen(
  void Function(T) onData, {
  Function? onError,
  void Function()? onDone,
  bool? cancelOnError,
}) =>
    subject.listen(///subject是GetStream对象
      onData,
      onError: onError,
      onDone: onDone,
      cancelOnError: cancelOnError ?? false,
    );
    
///GetStream#listen
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)///在前面代码中 RxNotifier.listen 中传入的 _updateTree 最终会被包装到这里,
    ..onError(onError)
    ..onDone(onDone)
    ..cancelOnError = cancelOnError;
  addSubscription(subs);/// 因为 _updateTree 被包装到了 LightSubscription 中,所以关注下 subs 在哪里用。。。执行 addSubscription
  onListen?.call();
  return subs;
}

  • _ObxState 中看到了一个熟悉的类 RxNotifier 在 RxInt的继承结构中我们也碰到了 RxNotifier ,这里不要混淆,此刻这里的 RxNotifier 是在 ObxWidget 中被初始化的和 Rx 流程没多大关系,用 _observer 来接收这个实例执行它的 listen 操作,将 _updateTree 给添加进去,_updateTree 中维护了 setState 函数,所以这里我可以猜测在某个时刻肯定会执行这个 _updateTree

  • RxNotifier 的 listen 函数会执行 obx 的 GetStream 的 listen 函数,在该函数中会新建一个 LightSubscription 对象,将之前的 _updateTree 维护到 LightSubscription 中并执行 addSubscription(subs);将 LightSubscription 添加到 _onData 集合中 _onData 是 GetStream 维护的一个类型为 LightSubscription 的一个 List 集合,可以理解为 _ObxState 的 initState 函数就是将 setState 函数给维护起来,方便以后调用

@override
Widget build(BuildContext context) =>
    RxInterface.notifyChildren(_observer, widget.build);///tag03 - 传入Obx的 RxNotifier
    
    
static T notifyChildren<T>(RxNotifier observer, ValueGetter<T> builder) {
  final _observer = RxInterface.proxy;///将 _observer 作为一个临时变量 , RxInterface.proxy 正常情况下是空,但是会作为中间变量暂存 RxNotifier 对象
  RxInterface.proxy = observer;///将在 _ObxState 中实例化的 RxNotifier 赋值给 RxInterface.proxy
  final result = builder();///外部传入的 Widget 对象,如果Widget中有 xxx.value 的操作说明这里有个 getValue 的操作,接下来看Rx系列
  if (!observer.canUpdate) {
    RxInterface.proxy = _observer;
    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;
}

  • 继续看 ObxWidget 的 build 流程,这里会执行 RxInterface.notifyChildren(_observer, widget.build) 传入当前 obx 的 RxNotifier,以及包裹的子控件

  • 执行 RxInterface 的 notifyChildren 函数,这里会用 _observer 变量来保存 RxInterface.proxy ,默认情况下 RxInterface.proxy 的值为 null,proxy 是一个 static 类型的变量,在这里会被赋值为 obx 的 RxNotifier

  • 执行 builder() 函数,注意啦,这个函数里面是 ObxWidget 包裹的子控件,所以里面如果有获取值的操作比如说 controller.count.value,那么就跟之前讲 Rx 的流程对接上了,所以作中还是要回到 get value 的操作。

T get value {///这里的 RxInterface.proxy 其实就是 Obx 中实例化的 RxNotifier
  RxInterface.proxy?.addListener(subject);///调用 Obx 中的 RxNotifier.addListener ,将变量中的 GetStream 添加到 Obx 中
  return _value;///返回默认值
}
  • 在 get value 中首先会执行 RxInterface.proxy?.addListener(subject) ,这个前面看过 RxInterface.proxy 已经被赋值为了obx 的 RxNotifier,这里首先会执行 RxNotifier 的 addListener ,参数是 Rx 的 GetStream,然后返回一个默认值,addListener 最终会执行 NotifyManager 的 addListener
void addListener(GetStream<T> rxGetx) { ///getValue操作实际上也就是添加一个监听
  if (!_subscriptions.containsKey(rxGetx)) {
    final subs = rxGetx.listen((data) {///每次执行Rx的set操作的时候都会执行这里传入的回调
      if (!subject.isClosed) subject.add(data);///执行Obx中的GetStream对象的add操作刷新界面
    });///rxGetx.listen 你会发现这里只有一个入参,这个入参数就是 onData ,所以这个 onData 是封装到了 Rx 的 GetStream 中的_onData集合中的,
    final listSubscriptions =                                                  ///在 set 操作的时候会遍历这个集合并执行这个onData
        _subscriptions[rxGetx] ??= <StreamSubscription>[];                      ///也就是说这时候会执行 if (!subject.isClosed) subject.add(data);
    listSubscriptions.add(subs);
  }
}
  • 注意此刻流程已经流传到了 obx 的 RxNotifier 中的 addListener,这里首先会判断 _subscriptions 集合中是否已经包含这个 Rx 的 GetStream ,由于是第一次执行所以 if 条件成立,执行 Rx 的 GetStream 的 listen 函数

  • Rx 的 GetStream 的 listen 函数传入的 onData 入参是自定义的入参,直接执行当前 obx 的 GetStream 的 add 函数,先记住呆会讲这个 add 做了什么

  • 前面讲过 listen 函数会执行 addSubscription ,所以 Rx 的 GetStream 中 _onData 集合会维护 subject.add(data) ,那么到这一步 Rx 与 obx 是不是就关联在一起了,好绕。。。。剩下的问题就是什么时候执行 subject.add(data),既然它是被通过函数的形式给维护起来的,那么必然在某一个地方会回调这个函数,这一步骤就是 set value 流程,get value的过程其实就是添加监听的过程,刷新逻辑还是要看 set value

set value(T val) {
  ///......
  subject.add(_value);///执行 Rx 的 GetStream 的 add 操作,而这个操作在Obx中已经封装好了
}

void add(T event) {
  assert(!isClosed, 'You cannot add event to closed Stream');
  _value = event;
  _notifyData(event);
}

void _notifyData(T data) {
  _isBusy = true;
  for (final item in _onData!) {
    if (!item.isPaused) {
      item._data?.call(data);
    }
  }
  _isBusy = false;
}

  • 核心代码其实就是一句 subject.add(_value);,这里执行 Rx 的 GetStream 的 add 操作,add 函数中会执行 _notifyData(event);

  • _notifyData 中遍历 _onData 集合,这个 _onData 是 Rx 的 _onData,上面不是讲过了吗,Rx 的 _onData 集合中维护了 obx 的 GetStream 的 add 操作,所以遍历 _onData 并执行 _data?.call(data);其实就是执行 subject.add(_value);即 obx 的 GetStream 的 add 操作

  • GetStream 的 add 操作其实也就是 _notifyData 函数,不过流程到这里的时候遍历的是 obx 的 _onData ,而 obx 的 _onData 封装的是 _updateTree 也就是 setState ,所以 set value 的操作最终执行的其实其实 setState

那么到这里呢,刷新流程也就讲完了,你会发现 GetX 其实就是对 setState 的封装,obx 的逻辑非常的绕,我这里写的文字呢也非常的干硬,建议大家自己对着看的时候利用好 debug,实在看的太晕了我这里还有自己录制的视频版本 GetX 状态管理 GetBuilder 以及 Obx 的实现原理