flutter dart mixin 姿势
在日常搬砖过程中经常会有 页面 或者 功能 可以 共用 或者 相互依赖 的情况,这时候我们可以 合理使用 混入功能。用来共用页面或者逻辑 减少代码冗余:
1.基本的变量,方法 共用与重载 变量的重新赋值
mixin 混入之后实际上就是一个整体,混入的顺序 重写方法 变量重新赋值 都会对整理产生影响。
mixin Swimmer { String name = '海豚'; void swim() { print("$name 会游泳"); } } mixin Flyer { String name = '燕子'; void fly() { print("$name 会飞"); } void eat() { print("eat $name 喜欢吃虫子"); } }
在 widget 中的使用:
class _PageMixinState extends State<PageMixin> with Swimmer, Flyer { @override void initState() { // TODO: implement initState super.initState(); swim(); // step 1 fly(); // step 2 name = '大猩猩'; // step 3 swim(); // step 4 fly(); // step 5 eat(); // step 6 } // step 7 @override void eat() { // TODO: implement eat super.eat(); //调用父类方法 也可以不用 print("eat $name 喜欢吃香蕉"); } @override Widget build(BuildContext context) { return const Placeholder(); } } 对应的输出: I/flutter (23523): 燕子 会游泳 I/flutter (23523): 燕子 会飞 I/flutter (23523): 大猩猩 会游泳 I/flutter (23523): 大猩猩 会飞 I/flutter (23523): eat 大猩猩 喜欢吃虫子 I/flutter (23523): eat 大猩猩 喜欢吃香蕉
mixin 混入顺序对变量的影响
- 燕子 会游泳
- 燕子 会飞
Swimmer Flyer 有各自的方法 分别是 swim() 和 fly(), 但是他们有同名的变量 name, 由于顺序原因 Flyer 中 name 变量得以保留, 最终变成 燕子 会游泳了,
- 大猩猩 会游泳
- 大猩猩 会飞
我们在 step 3 中我们对 name 重新赋值之后,最终变成 大猩猩 会飞
- eat 大猩猩 喜欢吃虫子
- eat 大猩猩 喜欢吃香蕉
我们在 step 7 中对 eat 函数重写,并且 调用 super.eat(); 此时 Flyer 中的 eat() 方法也会被调用,然而 name 还是 setp3 中被复制的 值
2.类型约束,访问约束类型 变量,方法
有时候我们编写 混类的时候,需要在 mixin 类中 别的类中的方法或者变量,例如: 调用StatefulWidget 方法 setState 使 Widget 刷新。这个时候我们可以 启用约束,这样 就能在 mixin 中操作对应的属性 或者方法
import 'package:flutter/cupertino.dart'; mixin Count<T extends StatefulWidget> on State<T> { int countTime = 60; countNum() { if (countTime > 1) { setState(() { countTime--; }); } } }
调用 Widget
class _PageMixinState extends State<PageMixin> with Count { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Text('$countTime'), ), floatingActionButton: FloatingActionButton( onPressed: () { countNum(); }, ), ); } }
这样就能在 mixin 方法中调用 setState 刷新 widget
3.mixin 中访问 另一个 mixin 变量,方法 on 关键字
由于我们不会吧 所有的 共用功能 写在 一个 mixin 中, 多个 mixin 可能存在相互依赖的关系:
mixin Work on WakingUp, Breakfast { doWork() { doWakingUp(); makeBreakfast(); print('开始上班 搬砖中 要搬一整天'); } } mixin WakingUp { doWakingUp() { print('闹钟响了要起床了'); } } mixin Breakfast { makeBreakfast() { print('开火做法'); } }
调用:
class _PageMixinState extends State<PageMixin> with WakingUp, Breakfast, Work { @override void initState() { /// 总的调用 doWork(); // TODO: implement initState super.initState(); } @override Widget build(BuildContext context) { return const Scaffold( body: Center(), ); } } 输出: I/flutter (23523): 闹钟响了要起床了 I/flutter (23523): 开火做法 I/flutter (23523): 开始上班 搬砖中 要搬一整天
每天上班前:起床-> 做饭 -> 到公司开始搬砖:
在这个场景中我们模拟 上班的过程,每一个过程都是一个 独立的环节,终止把各个独立的 环节 合成一个完整流程:
实际的工作中 业务的复杂性可能很高,怎么样 合理灵活的发挥使用 才是体现 coding 的艺术高低,设计的越巧妙合理 那么 技艺和艺术才能展现出来。追求永无止境