美文网首页Flutter
在 flutter 中使用枚举的技巧

在 flutter 中使用枚举的技巧

作者: 独立开发者猫哥 | 来源:发表于2022-11-06 22:20 被阅读0次

    在 flutter 中使用枚举的技巧

    前言

    例如,不管是谁在 Kotlin 之后,再开发 Dart 都对它带来的种种限制感到失望。

    其中之一是枚举类。单独使用枚举值是可以的,但是还有别的吗?你不得不用枚举,对吧?

    这篇文章将会推荐几个 enum 枚举的使用技巧。

    正文

    旧的方式, 通过 extension 扩展枚举值

    让我们提醒自己,这样的代码可能是什么样子的。下面是一组 ActivityType 。在某些时候,我们希望为每个活动分配一个数字和一个字符串值。也许我们的后端返回一个数字,但是我们当然不想在我们的应用程序代码中使用奇怪的数字来标记。相反,我们决定使用枚举。

    enum ActivityType {
    
      running,
    
      climbing,
    
      hiking,
    
      cycling,
    
      ski
    
    }
    
    
    extension ActivityTypeNumber on ActivityType {
    
      int get number {
    
        switch (this) {
    
          case ActivityType.running:
    
            return 1;
    
          case ActivityType.climbing:
    
            return 2;
    
          case ActivityType.hiking:
    
            return 5;
    
          case ActivityType.cycling:
    
            return 7;
    
          case ActivityType.ski:
    
            return 10;
    
        }
    
      }
    
    }
    extension ActivityTypeValue on ActivityType {
    
      String get value {
    
        switch (this) {
    
          case ActivityType.running:
    
            return 'Running';
    
          case ActivityType.climbing:
    
            return 'Climbing';
    
          case ActivityType.hiking:
    
            return 'Hiking';
    
          case ActivityType.cycling:
    
            return 'Cycling';
    
          case ActivityType.ski:
    
            return 'Skiing';
    
        }
    
      }
    
    }
    

    为了访问数字或 String 值:

    final climbingInt = ActivityType.climbing.number;
    final climbingString = ActivityType.climbing.value;
    

    现在使用新的枚举值方式

    幸运的是,随着 2022 年 5 月在 Google I/O 上发布 Flutter 3.0,我们不必再依赖这些令人长长的代码了。让我们使用新的和增强的枚举类重写代码。

    https://medium.flutterdevs.com/flutter-3-0-whats-new-in-flutter-12259bf090ba

    enum ActivityType {
    
      running(1, 'Running'),
    
      climbing(2, 'Climbing'),
    
      hiking(5, 'Hiking'),
    
      cycling(7, 'Cycling'),
    
      ski(10, 'Skiing');
    
    
      const ActivityType(this.number, this.value);
    
    
    
      final int number;
    
      final String value;
    
    }
    

    其实就是赋予了一些类的特性

    所以这次很聪明! 访问值或数值保持不变。

    在工作中,我们通常希望获得一个枚举或一个基于数字的值,这些数字是从后端接收的。

    或者,基于活动的字符串名称(比如,如果我们得到“攀登”并想将其映射到 ActivityType.)。这一切都很容易做到:

    enum ActivityType {
    
      running(1, 'Running'),
    
      climbing(2, 'Climbing'),
    
      hiking(5, 'Hiking'),
    
      cycling(7, 'Cycling'),
    
      ski(10, 'Skiing');
    
    
      const ActivityType(this.number, this.value);
    
    
    
      final int number;
    
      final String value;  static ActivityType getTypeByTitle(String title) =>
        ActivityType.values.firstWhere((activity) => activity.name == title);
      static ActivityType getType(int number) => ActivityType.values.firstWhere((activity) => activity.number == number);
    
    
      static String getValue(int number) => ActivityType.values.firstWhere((activity) => activity.number == number).value;
    
    }
    

    Name 是每个 enum 的默认属性,并返回一个该 enum 值的字符串,例如, activitytype.ski.name 是“ ski”。

    final activityType = ActivityType.getTypeByTitle('hiking');
    
    Console:
    I/flutter ( 2896): activity: ActivityType.hiking
    

    unknown 异常处理

    请记住,如果由于某种原因所提供的标题或数字不在您的活动标题/数字中,您将得到一个糟糕的状态异常。这个案子有用:

    正常访问

    final activityType = ActivityType.getType(7);
    final activityValue = ActivityType.getValue(7);
    print('activity: $activityType - $activityValue');
    
    Console:
    I/flutter (24956): activity: ActivityType.cycling - Cycling
    

    但这个不是:

    final activityType = ActivityType.getType(77);
    Console:
    
    ======== Exception caught by widgets library =======================================================
    
    The following StateError was thrown building ActivityListScreen(dirty, state: _ConsumerState#c9a6a):
    
    Bad state: No element
    ....
    

    这是因为我们没有提供或 Else ()子句。函数。为了不出现错误,我们可以默认为未知类型:

    enum ActivityType {
    
      running(1, 'Running'),
    
      climbing(2, 'Climbing'),
    
      hiking(5, 'Hiking'),
    
      cycling(7, 'Cycling'),
    
      ski(10, 'Skiing'),
    
      unknown(-1, '');
    
      const ActivityType(this.number, this.value);
    
      final int number;
    
      final String value;static ActivityType getTypeByTitle(String title) =>
        ActivityType.values.firstWhere((activity) => activity.name == title, orElse: () => ActivityType.unknown);
    
      static ActivityType getType(int number) =>
          ActivityType.values.firstWhere((activity) => activity.number == number, orElse: () => ActivityType.unknown);
    
    
      static String getValue(int number) =>
          ActivityType.values.firstWhere((activity) => activity.number == number, orElse: () => ActivityType.unknown).value;
    
    }
    

    extension 扩展处理枚举

    或者只是不添加未知类型,而是返回一个可为空的值。这需要我们向列表中添加一个扩展函数。我发现它在应用程序的其他部分也很有用,不仅仅是枚举:

    extension ListExtension<T> on List<T> {
    
      T? firstWhereOrNull(bool Function(T element) condition) {
    
        for (final element in this) {
    
          if (condition(element)) return element;
    
        }
    
        return null;
    
      }
    
    }
    

    然后我们的 ActivityType 看起来像这样:

    enum ActivityType {
    
      running(1, 'Running'),
    
      climbing(2, 'Climbing'),
    
      hiking(5, 'Hiking'),
    
      cycling(7, 'Cycling'),
    
      ski(10, 'Skiing');
    
    
      const ActivityType(this.number, this.value);
    
    
      final int number;
    
      final String value;  static ActivityType? getTypeByTitle(String title) =>
        ActivityType.values.firstWhereOrNull((activity) => activity.name == title);
    
      static ActivityType? getType(int number) =>
          ActivityType.values.firstWhereOrNull((activity) => activity.number == number);
    
      static String? getValue(int number) =>
          ActivityType.values.firstWhereOrNull((activity) => activity.number == number)?.value;
    
    }
    

    对于一些奇怪的输入数据,我们得到的是空值,而不是异常和红色屏幕。

    final activity = ActivityType.getTypeByTitle('abc');
    final activityType = ActivityType.getType(77);
    final activityValue = ActivityType.getValue(99);
    print('$activity - $activityType - $activityValue');
    
    Console:
    I/flutter ( 2896): null - null - null
    

    加入自定义函数 如 activityString()

    根据您的需要、后端返回的内容等,选择两种方法中的一种。

    还有一件事,当然可以使用非静态函数,比如下面的 activityString() :

    enum ActivityType {
    
      running(1, 'Running'),
    
      climbing(2, 'Climbing'),
    
      hiking(5, 'Hiking'),
    
      cycling(7, 'Cycling'),
    
      ski(10, 'Skiing');
    
    
      const ActivityType(this.number, this.value);
    
    
      final int number;
    
      final String value;  static ActivityType? getTypeByTitle(String title) =>
        ActivityType.values.firstWhereOrNull((activity) => activity.name == title);
    
      static ActivityType? getType(int number) =>
          ActivityType.values.firstWhereOrNull((activity) => activity.number == number);
    
      static String? getValue(int number) =>
          ActivityType.values.firstWhereOrNull((activity) => activity.number == number)?.value;
    
      String activityString(String userName) => '$userName is $value';
    
    }
    

    然后,对某个枚举调用它,得到一个漂亮的字符串,您可以立即在 UI 中使用该字符串:

    final userIsWorkingOut = ActivityType.climbing.activityString('Emily Jules');
    
    print('$userIsWorkingOut');
    
    Console:
    I/flutter (28053): Emily Jules is Climbing
    

    就是这样! 享受在 Flutter 中使用一个增强的枚举 ;)

    结束语

    如果本文对你有帮助,请转发让更多的朋友阅读。

    也许这个操作只要你 3 秒钟,对我来说是一个激励,感谢。

    祝你有一个美好的一天~


    © 猫哥

    本文由mdnice多平台发布

    相关文章

      网友评论

        本文标题:在 flutter 中使用枚举的技巧

        本文链接:https://www.haomeiwen.com/subject/buovtdtx.html