我们封装了哪些好用的Flutter Mixin

一、Mixin 的本质

  • 定义 :Mixin 是一种特殊的类,通过 mixin 关键字声明,不能直接实例化,但可以被其他类"混入"(使用 with 关键字)。

  • 核心思想:将可复用的代码片段注入到多个不相关的类中,实现代码的横向组合(而非纵向继承)。

二、Mixin 的工作原理

  • 线性化(Linearization) :Dart 使用线性化算法处理混入顺序。当多个 Mixin 存在时,它们的属性和方法会按 with 的声明顺序从右到左叠加(最后混入的优先级最高)。

    Dart 复制代码
    class MyWidget with MixinA, MixinB, MixinC {}
    // 方法解析顺序:MixinC → MixinB → MixinA → MyWidget
  • 冲突解决:如果多个 Mixin 有同名方法,后混入的会覆盖前面的(类似"最后一个生效"规则)。

三、Mixin vs 继承 vs 接口

特性 Mixin 继承 (extends) 接口 (implements)
复用方式 横向组合 纵向继承 强制实现契约
多重支持 是(with A,B 否(单继承)
代码复用 直接复用逻辑 复用父类实现 无默认实现
典型场景 跨类共享工具方法 "is-a"关系 "can-do"能力

四、我们在项目中封装哪些Mixin

1、AddListenerMixin

Dart 复制代码
mixin AddListenerMixin<T extends StatefulWidget> on State<T> {
  final Map<Listenable, VoidCallback> _registrationInfo = {};

  void addListener(Listenable listenable, VoidCallback listener) {
    listenable.addListener(listener);
    _registrationInfo[listenable] = listener;
  }

  @override
  void dispose() {
    for (var entry in _registrationInfo.entries) {
      entry.key.removeListener(entry.value);
    }
    _registrationInfo.clear();
    super.dispose();
  }
}

项目中使用的** AddListenerMixin 主要是简化 Listenable 对象(如 ValueNotifierAnimationController **等)的监听管理,自动处理监听器的注册和清理,避免内存泄漏。同时也可以减少dispose时的样板代码。

不过目前AddListenerMixin 不支持手动移除VoidCallback,也不支持批量操作。

2、SafeSetStateMixin

Dart 复制代码
mixin SafeSetStateMixin<T extends StatefulWidget> on State<T> {
  
  void safeSetState(VoidCallback fn) {
    fn.call();
    if (!mounted) return;
    final animStatus = ModalRoute.of(context)?.animation?.status;
    if (animStatus == null || animStatus == AnimationStatus.completed) {
      scheduleMicrotask(() {
        if (mounted) {
          setState(() {});
        }
      });
    } else {
      _listenRouteAnim();
      _needSetState = true;
    }
  }

  Animation? _routeAnim;
  bool _needSetState = false;

  void _listenRouteAnim() {
    _routeAnim?.removeStatusListener(_animStatusListener);
    _routeAnim = ModalRoute.of(context)?.animation;
    _routeAnim?.addStatusListener(_animStatusListener);
  }

  @override
  void deactivate() {
    _routeAnim?.removeStatusListener(_animStatusListener);
    _routeAnim = null;
    super.deactivate();
  }

  void _animStatusListener(AnimationStatus status) {
    if (_needSetState && status == AnimationStatus.completed) {
      _needSetState = false;
      safeSetState(() {});
    }
  }
}

SafeSetStateMixin 的作用

  • 避免在disposed状态下调用setState

  • 避免在动画未完成的情况下触发setState,通过监听动画状态,在动画完成后及时触发setState更新

  • 异步安全,通过 scheduleMicrotask 延迟 setState,避免在 build 过程中同步触发更

3、StreamControlMixin

Dart 复制代码
mixin StreamControlMixin<T extends StatefulWidget> on State<T> {
  final Set<StreamSubscription> _subscriptions = {};

  void addSubscription(StreamSubscription subscription) {
    if (subscription != null) {
      _subscriptions.add(subscription);
    }
  }

  bool removeSubscription(StreamSubscription subscription) {
    if (subscription != null) {
      return _subscriptions.remove(subscription);
    }
    return false;
  }

  void cancelAllEvents() {
    for (var subscription in _subscriptions) {
      try {
        subscription.cancel();
      } catch (e) {
        debugPrint('Error canceling subscription: $e');
      }
    }
    _subscriptions.clear();
  }

  bool hasSubscription(StreamSubscription subscription) {
    return _subscriptions.contains(subscription);
  }

  @override
  void dispose() {
    if (_subscriptions.isNotEmpty) {
      cancelAllEvents();
    }
    super.dispose();
  }
}

StreamControlMixin的作用

  • 提供统一的方式来管理StreamSubscription,支持手动添加、移除

  • 自动清理资源,在组件销毁时自动取消所有订阅,防止内存泄漏

  • 简化添加、移除流程,减少模版代码

五、总结

本篇主要是简单介绍了一下Mixin,总结分享了一下在项目我们封装了哪些Mixin,希望能够给读者带来一些思考。实际上个人认为封装的中心思想都是一致,仅是利用不同语言的特性。

相关推荐
2501_915106321 小时前
iOS混淆工具实战 金融支付类 App 的安全防护与合规落地
android·ios·小程序·https·uni-app·iphone·webview
alexhilton3 小时前
运行时着色器实战:实现元球(Metaballs)动效
android·kotlin·android jetpack
從南走到北4 小时前
JAVA国际版东郊到家同城按摩服务美容美发私教到店服务系统源码支持Android+IOS+H5
android·java·开发语言·ios·微信·微信小程序·小程序
LinXunFeng4 小时前
Flutter - 详情页初始锚点与优化
前端·flutter·开源
苦逼的搬砖工4 小时前
Flutter 文本输入:让用户与你的应用对话
flutter
苦逼的搬砖工4 小时前
Flutter Text 组件深度解析:从入门到精通
flutter
苦逼的搬砖工4 小时前
# 🎨 Flutter UI 组件深度指南
flutter
观熵5 小时前
Android 相机系统全景架构图解
android·数码相机·架构·camera·影像
Huntto6 小时前
在Android中使用libpng
android
君赏7 小时前
Petrel(雨燕) 新一代 Flutter Web 热更新框架.
flutter