3. 手撕Flutter getx 的 刷新机制

502 阅读1分钟
  • getx 确实好用,但是只知道用确实少了什么,下面我根据我的研究通过流程图,大概的拆分出他们的运行机制;
  • 其实主要原理类似vue 通过 get进行收集,通过set来进行通知

demo1

  • 定义一个 var count = 0.obs; 其实就是 RxInt对象 ;
  • Obx 其实就是一个StatefullWidget
  1. RxInt extend Rx<T> extend _RxImpl<T> extend RxNotifier<T> with RxObjectMixin<T>
  2. mixin RxObjectMixin<T> on NotifyManager<T>
    • late T _value;
    • get/set 方法
     T get value {
       RxInterface.proxy?.addListener(subject);
       return _value;
     }
     set value(T val) {
         _value = val;
         subject.add(_value);
     }
  • NotifyManager<T>
    • GetStream<T> subject = GetStream<T>();

    • 这里就存在一个subject属性

    • 这个 GetStream主要的作用就是 存储 subject.listen(f(value)),主要是存储监听函数,等到某个时机比如 set方法触发,就会调用 f(value)函数;

  1. 说明任何一个 RxNotifier都会有个 GetStream 对象

  2. Obx的 state _ObxState内部

class _ObxState extends State<ObxWidget> {
  //初始化一个RxNotifer
  final _observer = RxNotifier();
  late StreamSubscription subs;

  @override
  void initState() {
    super.initState();
    // 这里这样调用,其实 内部还是会调用 _observer.subject.listen(_updateTree, cancelOnError: false)
    subs = _observer.listen(_updateTree, cancelOnError: false);
  }

  void _updateTree(_) {
    if (mounted) {
      setState(() {});
    }
  }

demo


class GetxDemo extends StatelessWidget {
   GetxDemo({Key? key}) : super(key: key);

  // RxInt count = RxInt(0);
  // var count = Rx<double>(0);
  var count = 0.obs;

  @override
  Widget build(BuildContext context) {

    // $count 会调用 toString 
    print("build : $count : ${count.value}");

    return Scaffold(
      appBar: AppBar(title: const Text("Getx"),),
      body: Center(
        child: Column(
          children: [
            // 局部刷新
            Obx(() => Text(
              "count的值为: $count",
              style: TextStyle(color: Colors.red, fontSize: 30),
            )),
            ElevatedButton(onPressed: () {
              count = count + 1;
            }, child: const Text("加1")),
          ],
        ),
      ),
    );
  }
}

分析 流程

大概的流程

    1. 就是 Obx 通过 _observer ,根据 count的 get方法进行收集;
    1. 通过count的set方法,根据注册的回调进行更新

getx.drawio.png