记录关于Flutter中枚举使用的一些理解

1,282 阅读4分钟

枚举是在日常开发中经常使用的一种类型,Flutter 下的枚举,大概分为三个阶段:

1. Dart2.7之前版本

2. Dart2.7扩展函数版本

3. Flutter3.0的增强枚举类版本

以枚举 AnimalEnum 举例,解决两个常用场景:

枚举定义:

enum AnimalEnum {
  dog,
  cat,
  chicken,
  horse,
}

场景1 我们需要在业务层获取到枚举值映射的关联数据: 1.int值 2.枚举字符串 3.中文名称(label) 4.其他相关联的属性,(例如声音sound)

场景2 我们需要在业务层根据后端返回的枚举int值/枚举字符串来转换成枚举,以便进行一些逻辑判断,例如: 根据:字符串【"dog"】或者int值【101】 获取到枚举: AnimalEnum.dog;

1. Dart2.7之前版本

**场景1:**在Dart2.7的扩展函数发布之前,一般是新建一个顶级函数/工具类内部函数,使用swtich case来返回枚举值对应的关联数据:

///枚举转换int值
int getAnimalEnumInt(AnimalEnum animalEnum) {
  switch (animalEnum) {
    case AnimalEnum.dog:
      return 101;
    case AnimalEnum.cat:
      return 102;
    case AnimalEnum.chicken:
      return 103;
    case AnimalEnum.horse:
      return 104;
  }
}

///枚举转换字符串
String getAnimalEnumStr(AnimalEnum animalEnum) {
  switch (animalEnum) {
    case AnimalEnum.dog:
      return 'dog';
    case AnimalEnum.cat:
      return 'cat';
    case AnimalEnum.chicken:
      return 'chicken';
    case AnimalEnum.horse:
      return 'horse';
  }
}

///枚举转换label
String getAnimalEnumLabel(AnimalEnum animalEnum) {
  switch (animalEnum) {
    case AnimalEnum.dog:
      return '小狗';
    case AnimalEnum.cat:
      return '小猫';
    case AnimalEnum.chicken:
      return '坤坤';
    case AnimalEnum.horse:
      return '小马';
  }
}

///枚举转换声音
String getAnimalEnumSound(AnimalEnum animalEnum) {
  switch (animalEnum) {
    case AnimalEnum.dog:
      return '汪汪';
    case AnimalEnum.cat:
      return '喵喵';
    case AnimalEnum.chicken:
      return '鸡你太美';
    case AnimalEnum.horse:
      return '吁~';
  }
}

**场景2:**新建一个顶级函数/工具类内部函数,根据入参值来使用swtich case来返回对应的枚举值:

//根据枚举int值转换成枚举
AnimalEnum? getAnimalEnumFromInt(int enumInt) {
  switch (enumInt) {
    case 101:
      return AnimalEnum.dog;
    case 102:
      return AnimalEnum.cat;
    case 103:
      return AnimalEnum.chicken;
    case 104:
      return AnimalEnum.horse;
    default:
      return null;
  }
}

//根据枚举String值转换成枚举
AnimalEnum? getAnimalEnumFromStr(String enumStr) {
  switch (enumStr) {
    case 'dog':
      return AnimalEnum.dog;
    case 'cat':
      return AnimalEnum.cat;
    case 'chicken':
      return AnimalEnum.chicken;
    case 'horse':
      return AnimalEnum.horse;
    default:
      return null;
  }
}

2. Dart2.7扩展函数版本

随着dart2.7的发布,Dart新增了扩展函数,使枚举相关的代码定义、调用更加简洁

dart2 7

**场景1:**在dart的扩展函数发布之后,一般是对枚举新建扩展函数,根据对应的枚举值来转换成关联数据,外部调用直接使用枚举的扩展函数即可:

///对枚举值定义一个扩展函数
extension AnimalEnumExt on AnimalEnum {
  ///枚举转换int值
  int get animalEnumInt {
    //扩展函数内部可以直接使用[this]关键字获取当前实例
    switch (this) {
      case AnimalEnum.dog:
        return 101;
      case AnimalEnum.cat:
        return 102;
      case AnimalEnum.chicken:
        return 103;
      case AnimalEnum.horse:
        return 104;
    }
  }

  ///枚举转换字符串
  String get animalEnumStr {
    switch (this) {
      case AnimalEnum.dog:
        return 'dog';
      case AnimalEnum.cat:
        return 'cat';
      case AnimalEnum.chicken:
        return 'chicken';
      case AnimalEnum.horse:
        return 'horse';
    }
  }

  ///枚举转换label
  String get animalEnumLabel {
    switch (this) {
      case AnimalEnum.dog:
        return '小狗';
      case AnimalEnum.cat:
        return '小猫';
      case AnimalEnum.chicken:
        return '坤坤';
      case AnimalEnum.horse:
        return '小马';
    }
  }

  ///枚举转换声音
  String get animalEnumSound {
    switch (this) {
      case AnimalEnum.dog:
        return '汪汪';
      case AnimalEnum.cat:
        return '喵喵';
      case AnimalEnum.chicken:
        return '鸡你太美';
      case AnimalEnum.horse:
        return '吁~';
    }
  }
}

///业务层调用
///1.手动导如入扩展函数所在的文件包名(这个不太智能)
import 'package:xxxx/AnimalEnumExt.dart';
///2.业务层使用扩展函数
test() {
  int enumInt = AnimalEnum.dog.animalEnumInt;
  String enumStr = AnimalEnum.dog.animalEnumStr;
  String enumLabel = AnimalEnum.dog.animalEnumLabel;
  String enumSound = AnimalEnum.dog.animalEnumSound;
}

**场景2:**对枚举关联类型新建扩展函数,根据对应的关联值来转换成关联数据,外部调用直接使用对应类型的扩展函数即可(以枚举int值举例):

///对int值定义一个扩展函数
extension AnimalEnumIntExt on int? {
  AnimalEnum? get animalEnum {
    switch (this) {
      case 101:
        return AnimalEnum.dog;
      case 102:
        return AnimalEnum.cat;
      case 103:
        return AnimalEnum.chicken;
      case 104:
        return AnimalEnum.horse;
      default:
        return null;
    }
  }
}

///2.业务层使用扩展函数
test() {
  int intVar = 101;
  AnimalEnum? animalEnum = intVar.animalEnum;
}

3. Flutter3.0:的增强枚举类版本

随着Flutter3.0的发布,google官方对于枚举值进行了一波史诗加强,使enum使用更方便了.

**场景1:**在Flutter3.0发布之后,直接在枚举构造方法内部定义相关属性,枚举值声明处进行声明即可:

///定义一个增强型枚举
enum AnimalEnum {
  dog(101, '小狗', '汪汪'),
  cat(102, '小猫', '喵喵'),
  chicken(103, '坤坤', '鸡你太美'),
  horse(104, '小马', '吁~');

  const AnimalEnum(this.number, this.label, this.sound);

  final int number;

  final String label;

  final String sound;
}

///业务层调用,直接使用枚举值的属性即可
test() {
  int enumInt = AnimalEnum.dog.number;
  ///name是枚举值自身的get方法,可以直接获取到枚举字符串
  String enumStr = AnimalEnum.dog.name;
  String enumLabel = AnimalEnum.dog.label;
  String enumSound = AnimalEnum.dog.sound;
}

**场景2:**直接在枚举内部定义静态方法,根据属性去匹配查找对应的枚举值:

///定义一个增强型枚举
enum AnimalEnum {
  dog(101, '小狗', '汪汪'),
  cat(102, '小猫', '喵喵'),
  chicken(103, '坤坤', '鸡你太美'),
  horse(104, '小马', '吁~');

  const AnimalEnum(this.number, this.label, this.sound);

  final int number;

  final String label;

  final String sound;

  ///通过number属性直接去匹配
  static AnimalEnum? getEnumByInt(int enumInt) {
    try {
      return AnimalEnum.values
          .firstWhere((element) => element.number == enumInt);
    } catch (e) {
      return null;
    }
  }

  ///通过Str属性直接去匹配
  static AnimalEnum? getEnumByStr(String enumStr) {
    try {
      //byName是dart2.15版本之后引入的新api,通过字符串去寻找对应的枚举值,注意catch处理
      return AnimalEnum.values.byName(enumStr);
    } catch (e) {
      return null;
    }
  }

  ///通过label属性直接去匹配
  static AnimalEnum? getEnumByLabel(String enumLabel) {
    try {
      return AnimalEnum.values
          .firstWhere((element) => element.label == enumLabel);
    } catch (e) {
      return null;
    }
  }
}

///业务层调用,直接使用枚举内部的静态方法
test1() {
  int dogInt = 101;
  AnimalEnum? animalEnum0 = AnimalEnum.getEnumByInt(dogInt);

  String dogLabel = 'dog';
  AnimalEnum? animalEnum1 = AnimalEnum.getEnumByStr(dogLabel);

  String doglabel = '小狗';
  AnimalEnum? animalEnum2 = AnimalEnum.getEnumByLabel(dogLabel);
}

如理解有误差,请随时批评~