欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

封裝flutter狀態(tài)管理工具示例詳解

 更新時(shí)間:2022年11月14日 16:59:13   作者:李小轟_Rex  
這篇文章主要為大家介紹了封裝flutter狀態(tài)管理工具示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

關(guān)于 Flutter 狀態(tài)管理,公司項(xiàng)目使用的是Bloc方案。Bloc 其實(shí)本質(zhì)上是 provider 的封裝擴(kuò)展庫,整體通過 InheritedWidget 、Notifier 外加 Stream中轉(zhuǎn)實(shí)現(xiàn)狀態(tài)變更通知。

關(guān)于 Bloc 實(shí)現(xiàn)原理,有興趣的同學(xué)可以觀看這篇文章 Bloc原理解析

RxBinder

撇開Bloc內(nèi)部實(shí)現(xiàn)策略,小轟嘗試基于數(shù)據(jù)驅(qū)動模型,自定義一套狀態(tài)管理工具。構(gòu)思如下:

主要成員如下:

  • RxBinderData: 數(shù)據(jù)模型基類,內(nèi)部封裝變更通知
  • RxBinder: 核心類,用于關(guān)聯(lián)訂閱關(guān)系

代碼實(shí)現(xiàn)

創(chuàng)建一個(gè)工具類用于注冊和發(fā)送通知

///使用callback的形式管理通知
class RxNotifier {
  List<VoidCallback> _listeners = [];
  void addListener(VoidCallback listener) {
    _listeners.add(listener);
  }
  void remove(VoidCallback listener) {
    if (_listeners.contains(listener)) {
      _listeners.remove(listener);
    }
  }
  ///通知
  void notify() {
    if (_listeners.isEmpty) return;
    for (final entry in _listeners) {
      entry.call();
    }
  }
}

數(shù)據(jù)模型應(yīng)該具備兩個(gè)特性:當(dāng)數(shù)據(jù)被使用時(shí),添加監(jiān)聽;當(dāng)數(shù)據(jù)發(fā)生改變時(shí)發(fā)送變更通知。

///數(shù)據(jù)模型基類,(封裝變更通知)
class RxBinderData<T> {
  late T _value;
  late String uuid;
  RxNotifier subject = RxNotifier();
  RxBinder? _rxBinder;
  RxBinderData(this._value, {RxBinder? value}) {
    uuid = Uuid().v4();
    bindRx(value);
  }
  void bindRx(RxBinder? value) {
    _rxBinder = value;
  }
  @override
  String toString() {
    return value.toString();
  }
  T get value {
    //添加監(jiān)聽,變更通知注冊
    _rxBinder?.register(uuid, subject);
    return _value;
  }
  set value(T val) {
    _value = val;
    notify();
  }
  void notify() {
    //通知數(shù)據(jù)發(fā)生變更
    subject.notify();
  }
}

創(chuàng)建一個(gè)中轉(zhuǎn)工具類,用于統(tǒng)一管理數(shù)據(jù)變更時(shí)的消息分發(fā)和訂閱關(guān)系

class RxBinder {
  Map<RxNotifier, String> _subjects = {};
  ///訂閱者, key是訂閱的數(shù)據(jù)id, value是訂閱數(shù)據(jù)發(fā)生變化時(shí)的通知回調(diào)
  Map<String, List<VoidCallback>> _subscriber = {};
  //注冊
  void register(String uuid, RxNotifier subject) {
    if (!_subjects.containsKey(subject)) {
      subject.addListener(() {
        _notify(uuid);
      });
      _subjects[subject] = '';
    }
  }
  //添加訂閱關(guān)系
  void addListener(String uuid, VoidCallback listener) {
    if (!_subscriber.containsKey(uuid)) {
      //key不存在
      _subscriber[uuid] = [listener];
    } else {
      //key已存在
      List<VoidCallback> list = _subscriber[uuid]!;
      if (!list.contains(listener)) {
        list.add(listener);
        _subscriber[uuid] = list;
      }
    }
  }
  //通知訂閱者
  void _notify(String uuid) {
    if (_subscriber.containsKey(uuid)) {
      final list = _subscriber[uuid];
      if (list != null && list.isNotEmpty) {
        for (final entry in list) {
          entry.call();
        }
      }
    }
  }
}

控制刷新組件

typedef WidgetCallback = Widget Function(BuildContext context);
class RxBindWidget extends StatefulWidget {
  final WidgetCallback builder;
  final List<RxBinderData> binders;
  const RxBindWidget(this.builder, this.binders, {Key? key}) : super(key: key);
  @override
  _RxBindWidgetState createState() => _RxBindWidgetState();
}
class _RxBindWidgetState extends State<RxBindWidget> {
  RxBinder rxBinder = RxBinder();
  @override
  void initState() {
    super.initState();
    for (final entity in widget.binders) {
      //數(shù)據(jù)源綁定Rx
      entity.bindRx(rxBinder);
      rxBinder.addListener(entity.uuid, notifyDataChange);
    }
  }
  void notifyDataChange() {
    setState(() {});
  }
  @override
  Widget build(BuildContext context) {
    return widget.builder(context);
  }
}

Demo 完美運(yùn)行

///基礎(chǔ)數(shù)據(jù)類型以int作為栗子
extension IntExtension on int {
  RxInt get rex => RxInt(this);
  //綁定Rx通知
  void bindRx(RxBinder? value) {
    rex.bindRx(value);
  }
}
///具體業(yè)務(wù)的擴(kuò)展類
class RxInt extends RxBinderData<int> {
  RxInt(int value) : super(value);
  RxInt operator +(int other) {
    value = value + other;
    return this;
  }
  RxInt operator -(int other) {
    value = value - other;
    return this;
  }
}
class Logic {
  RxInt count = 0.rex;
  void increase() => ++count;
}
class TestRxBinder extends StatelessWidget {
  final Logic logic = Logic();
  TestRxBinder({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RxBindWidget((context) {
          return _child(context);
        }, [logic.count]),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => logic.increase(),
        child: Icon(Icons.add),
      ),
    );
  }
  Widget _child(BuildContext context) {
    return Text(
      '點(diǎn)擊了 ${logic.count.value} 次',
    );
  }
}

以上就是封裝flutter狀態(tài)管理工具示例詳解的詳細(xì)內(nèi)容,更多關(guān)于flutter狀態(tài)管理封裝的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論