Flutter getx 状态管理

flutter 如何实现状态管理?

Flutter 要是实现状态管理wiget必须继承StatefulWidget,调用setState((){}),当然getx也不例外,

getx 状态管理

scala 复制代码
class HomeController extends GetxController {
    final count = 0.obs;
}

class HomePage extends GetView<HomeController> {
  @override
  Widget build(BuildContext context) {
     return Center(
            child: Obx(() => Text("${controller.currentPage.value}"))
            );
  }
}

Obx

Obx 继承ObxWidget继承StatefulWidget

scala 复制代码
abstract class ObxWidget extends StatefulWidget {
  const ObxWidget({Key? key}) : super(key: key);
  @override
  _ObxState createState() => _ObxState();

  @protected
  Widget build();
}

class _ObxState extends State<ObxWidget> {
  //obx的 RxNotifier 
  ///很重要,会有2个RxNotifier
  //1.obx的RxNotifier
  //Rxint的RxNotifier
  final _observer = RxNotifier();
  late StreamSubscription subs;

  @override
  void initState() {
    super.initState();
    //设置监听
    //给getStream 设置参数
    //1.创建LightSubscription
    //2.onData() = _updateTree 更新widget的方法
    //3.加入监听列表
    subs = _observer.listen(_updateTree, cancelOnError: false);
  }
  
  //更新的关键方法
  //猜测当rxint.setValue时,会调用此方法来更新widget
  void _updateTree(_) {
    if (mounted) {
      setState(() {});
    }
  }

  @override
  void dispose() {
    subs.cancel();
    _observer.close();
    super.dispose();
  }
  
  //通过notifyChildren创建widget
  //
  @override
  Widget build(BuildContext context) =>
      RxInterface.notifyChildren(_observer, widget.build);
}

RxNotifier

scss 复制代码
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;
  
  //1.obx_rxnotifier.addlistener(rxInt_getstream)
  //2.给rxInt_getstream设置监听
  //3.ondata = (data) {
  //      if (!subject.isClosed) obx_subject.add(data);
  //    }
  //4.当value 值更新时,触发 obx_getsteam的ondata= setstate()更新widget
  void addListener(GetStream<T> rxGetx) {
    if (!_subscriptions.containsKey(rxGetx)) {
      //设置一个监听  
      final subs = rxGetx.listen(
      (data) {
        if (!subject.isClosed) subject.add(data);
      }
      );
      final listSubscriptions =
          _subscriptions[rxGetx] ??= <StreamSubscription>[];
      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,
      );

 
  void close() {
    _subscriptions.forEach((getStream, _subscriptions) {
      for (final subscription in _subscriptions) {
        subscription.cancel();
      }
    });

    _subscriptions.clear();
    subject.close();
  }
}

GetStream

csharp 复制代码
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>>[];

  bool? _isBusy = false;

  FutureOr<bool?> removeSubscription(LightSubscription<T> subs) async {
    if (!_isBusy!) {
      return _onData!.remove(subs);
    } else {
      await Future.delayed(Duration.zero);
      return _onData?.remove(subs);
    }
  }

  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;
  
  //2种情况
  //1.rxint 值更新了,执行的时(data){obx_getstream.add()}
  //2.obx_stream 执行的是 setstate((){}) 刷新widget
  void _notifyData(T data) {
    _isBusy = true;
    for (final item in _onData!) {
      if (!item.isPaused) {
        item._data?.call(data);
      }
    }
    _isBusy = false;
  }

  T? _value;

  T? get value => _value;
  
  //1.rxint 当value更新时,调用 _notifyData,
  //2.value值更新,触发,obx的getstream 的add,
  void add(T event) {
    assert(!isClosed, 'You cannot add event to closed Stream');
    _value = event;
    //
    _notifyData(event);
  }

  bool get isClosed => _onData == null;


  void close() {
    assert(!isClosed, 'You cannot close a closed Stream');
    _notifyDone();
    _onData = null;
    _isBusy = null;
    _value = null;
  }
  
  //obx
  //1.创建LightSubscription
  //2.onData() 更新widget的方法
  //3.加入监听列表
  // rxInt
  //1.把onData加入到监听 
  /// rxint 也要加入监听
  // onData = (data){obx_subject.add(data)}
  //加入rxint 的监听列表
  //当value更新时
  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;
  }

  Stream<T> get stream =>
      GetStreamTransformation(addSubscription, removeSubscription);
}

RxInterface 重点

会给proxy 设置2次notifier

csharp 复制代码
abstract class RxInterface<T> {
  //静态全局可用,
  //
  static RxInterface? proxy;

  StreamSubscription<T> listen(void Function(T event) onData,
      {Function? onError, void Function()? onDone, bool? cancelOnError});
  
  static T notifyChildren<T>(RxNotifier observer, ValueGetter<T> builder) {
    //1.首次  _observer = null
    final _observer = RxInterface.proxy;
    //1.给proxy 设置 obx的 rxNotifiter
    //上文说到此时有2个rxNotifiter
    //此时的是obx的
    RxInterface.proxy = observer;
    //执行构建widget方法
    //看{controller.count.value}
    final result = builder();
    //reset null
    RxInterface.proxy = _observer;
    //返回widget
    return result;
  }
}

0.obs是什么? RxInt

rxint的RxNotifier

controller.count.value执行的是RxObjectMixin.value

class RxInt extends Rx<int> extends _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> on NotifyManager<T>

dart 复制代码
extension IntExtension on int {
  RxInt get obs => RxInt(this);
}

RxObjectMixin

ini 复制代码
mixin RxObjectMixin<T> on NotifyManager<T> {
  late T _value;

  void refresh() {
    subject.add(value);
  }

  T call([T? v]) {
    if (v != null) {
      value = v;
    }
    return value;
  }

  bool firstRebuild = true;
  bool sentToStream = false;
 
  //controller.count.value = 1   
  //1.执行getStream.add()
  ////2.rxint 值更新了,执行的时(data){obx_getstream.add()}
  //3.obx_stream 执行的是 setstate((){}) 刷新widget
  set value(T val) {
    if (subject.isClosed) return;
    sentToStream = false;
    if (_value == val && !firstRebuild) return;
    firstRebuild = false;
    _value = val;
    sentToStream = true;
    subject.add(_value);
  }
  
  //执行rxint的value
  //1.此时的RxInterface.proxy = obx的rxNotifiter,
  //2.将rxint的getStream 设置给obx
  // obx_rxnotifiter.addListener(rxint_subject)
  //
  // rxint 加入监听,
  // rxint_getstream值的更新触发obx_getsream的setState()更新widget
  T get value {
    RxInterface.proxy?.addListener(subject);
    return _value;
  }

  Stream<T> get stream => subject.stream;

  
  StreamSubscription<T> listenAndPump(void Function(T event) onData,
      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
    final subscription = listen(
      onData,
      onError: onError,
      onDone: onDone,
      cancelOnError: cancelOnError,
    );

    subject.add(value);

    return subscription;
  }

  void bindStream(Stream<T> stream) {
    final listSubscriptions =
        _subscriptions[subject] ??= <StreamSubscription>[];
    listSubscriptions.add(stream.listen((va) => value = va));
  }
}

流程图

相关推荐
光影少年16 分钟前
前端线上出现白屏如何排查问题所在,利用第三方的工具都有哪些
前端·学习·web安全·前端框架
傅里叶33 分钟前
Flutter项目使用 buf.build
flutter
恋猫de小郭2 小时前
iOS 26 开始强制 UIScene ,你的 Flutter 插件准备好迁移支持了吗?
android·前端·flutter
yuanlaile3 小时前
Flutter开发HarmonyOS鸿蒙App商业项目实战已出炉
flutter·华为·harmonyos
CodeCaptain3 小时前
可直接落地的「Flutter 桥接鸿蒙 WebSocket」端到端实施方案
websocket·flutter·harmonyos
路光.4 小时前
一.React相关面试真题
前端·react.js·前端框架
stringwu4 小时前
Flutter 中的 MVVM 架构实现指南
前端·flutter
球球和皮皮6 小时前
Babylon.js学习之路《添加自定义摇杆控制相机》
javascript·3d·前端框架·babylon.js
消失的旧时光-194316 小时前
Flutter 异步体系终章:FutureBuilder 与 StreamBuilder 架构优化指南
flutter·架构