我们封装了哪些好用的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,希望能够给读者带来一些思考。实际上个人认为封装的中心思想都是一致,仅是利用不同语言的特性。

相关推荐
程序员江同学40 分钟前
Kotlin/Native 编译流程浅析
android·kotlin
移动开发者1号1 小时前
Kotlin协程与响应式编程深度对比
android·kotlin
花花鱼11 小时前
android studio 设置让开发更加的方便,比如可以查看变量的类型,参数的名称等等
android·ide·android studio
alexhilton12 小时前
为什么你的App总是忘记所有事情
android·kotlin·android jetpack
小蜜蜂嗡嗡15 小时前
flutter封装vlcplayer的控制器
前端·javascript·flutter
AirDroid_cn15 小时前
OPPO手机怎样被其他手机远程控制?两台OPPO手机如何相互远程控制?
android·windows·ios·智能手机·iphone·远程工作·远程控制
尊治15 小时前
手机电工仿真软件更新了
android
xiangzhihong818 小时前
使用Universal Links与Android App Links实现网页无缝跳转至应用
android·ios
车载应用猿19 小时前
基于Android14的CarService 启动流程分析
android