【问题标题】:What's the best practice to keep all the constants in Flutter?在 Flutter 中保留所有常量的最佳做法是什么?
【发布时间】:2019-06-01 19:32:07
【问题描述】:

最好的编程实践是什么

在 Flutter 中创建一个常量类

保留所有应用程序常量以便于参考。我知道 Dart 中有 const 关键字用于创建常量字段,但是可以将 static 与 const 一起使用,还是会在运行时产生内存问题。

class Constants {
static const String SUCCESS_MESSAGE=" You will be contacted by us very soon.";
}

【问题讨论】:

  • 只是一点评论。在 Dart 中,与大多数其他语言不同,它对常量有一个 lowerCamelCase 的命名约定。

标签: static dart flutter constants


【解决方案1】:

这完全取决于您。
使用静态没有缺点。
实际上 const 是类中的字段所必需的。

【讨论】:

  • 但是不使用'static const'关键字会导致内存问题吗?怎么来的?
  • 你为什么这么认为?不同之处在于 const 使其成为可执行文件的数据部分的一部分,而非 const 使代码可以创建代码部分的实例部分(当编译为本机代码时)。在创建实例后,这将需要更多内存用于非常量。 Dart 还规范了 const 值。如果您使用相同的参数值多次调用 const 构造函数,分布在您的应用程序代码中,它将每次返回相同的实例。
  • 我只是担心使用过多的静态 const 变量可能会占用堆内存中的太多空间,因为它毕竟是静态的。
  • 运行时创建对象的代码指令不会占用更少的空间。只要您不添加大 BLOBS,这不会成为问题,您也不能在 for 循环中创建 const。如果您需要单独手动添加每个 const,您将很难将其显示在内存使用量中。
【解决方案2】:

编辑

现在 --dart-define 标志已添加到 Flutter 的不同命令行中,以下答案不再适用。

而只是在任何你想要的地方声明常量,并可能参考其他答案。


虽然static const 不存在技术问题,但在架构上您可能希望采用不同的方式。

Flutter 倾向于没有有任何全局/静态变量并使用 InheritedWidget。

这意味着你可以写:

class MyConstants extends InheritedWidget {
  static MyConstants of(BuildContext context) => context. dependOnInheritedWidgetOfExactType<MyConstants>();

  const MyConstants({Widget child, Key key}): super(key: key, child: child);

  final String successMessage = 'Some message';

  @override
  bool updateShouldNotify(MyConstants oldWidget) => false;
}

然后插入到你应用的根目录:

void main() {
  runApp(
    MyConstants(
      child: MyApp(),
    ),
  );
}

并这样使用:

@override
Widget build(BuilContext context) {
  return Text(MyConstants.of(context).successMessage);
}

这比static const 有更多的代码,但有很多优点:

  • 支持热重载
  • 易于测试和模拟
  • 可以用比常量更动态的东西替换,而无需重写整个应用程序。

但同时它:

  1. 不会消耗更多内存(继承的小部件通常创建一次)
  2. 高性能(获取 InheritedWidget 是 O(1))

【讨论】:

  • “Flutter 往往没有任何全局/静态变量并使用 InheritedWidget”。话虽如此?我来自传统的 Java 开发,这感觉非常 hacky ...
  • @Wecherowski 它隐含在 Flutter 所公开的内容中。与 InheritedWidgets 相比,静态变量非常非常少。你可以使用任何你喜欢的东西。
  • “Flutter 往往没有任何全局/静态变量并使用 InheritedWidget”。常量根据定义没有变量。因此我不明白,你试图用 InheritedWidget 解决什么。
  • @tvw "constants" 还包括诸如 "isInDebugMode" 或当前平台之类的内容。它们是构建的常量,但可能会在构建之间发生变化。在处理这些问题时,使用 InheritedWidgets 可以简化工作流程,例如模拟它们的值,或在开发模式下实时更改它。
  • Dart 文档明确指出“避免定义仅包含静态成员的类”。 dart.dev/guides/language/effective-dart/design
【解决方案3】:

我首选的解决方案是制作自己的 Dart 库。

新建一个名为constants.dart的dart文件,添加如下代码:

const String SUCCESS_MESSAGE=" You will be contacted by us very soon.";

编辑:99% 的情况下,您不需要在文件顶部使用 library library_name; 之类的语句明确命名您的 dart 库,而且您可能不应该 (reference)。
即使您省略了这一行,您的文件仍将是库!它只会被隐式命名。

然后将以下导入语句添加到需要访问常量的任何 dart 文件的顶部:

import 'constants.dart' as Constants;

请注意,如果constants.dart 位于不同的目录中,那么您需要在导入语句中指定constants.dart 的路径。

编辑:在指定库前缀时使用lowercase_with_underscores

在这个例子中:

你可以使用相对路径:

import '../assets/constants.dart' as constants;

或lib目录的绝对路径:

import 'package:<your_app_name>/assets/constants.dart' as constants;

现在您可以使用以下语法轻松访问常量:

String a = Constants.SUCCESS_MESSAGE;

【讨论】:

  • 我的方法非常相似:我只有一个名为“constants”的文件夹,里面有一堆文件,“constants.dart”作为导入文件,然后在 lib 根目录中我有“ constants.dart”,在 export "constants/constants.dart"; 内有一行。然后我刚刚在 VSCode 中创建了一个快捷方式 sn-p,前缀为“_iconst”,它为我创建了这样的导入 import 'package:&lt;your_app_name&gt;/constants.dart' as Constants;
  • 这种方法对我不起作用。找不到没有路径的“constants.dart”,因为它不在同一个文件夹中。即使它直接位于 /lib 中也不行。
  • 如果你想像 JS 一样导入单个常量怎么办?
  • library constants;有什么用
  • 它让我们知道该文件是一个库stackoverflow.com/questions/10157598/…
【解决方案4】:

对于所有常量,只需在 lib 文件夹或 lib/util 文件夹下创建 constants.dart 文件,然后将所有常量变量保存如下:

 const SUCCESS_MESSAGE=" You will be contacted by us very soon.";

 // Api related 
 const apiBaseURL = "https://baseurl.com";
    
 const userLoginApi = "login";
 const userSignupApi = "signup";
    
 // Shared Preference keys 
 const kDeviceName = "device_name";
 const kDeviceUDID = "device_id";

 // Asset Constants
 const navBarLogoImage = "assets/images/home_images/sample.png
   

然后在需要的类中导入constants.dart文件,直接使用。

【讨论】:

    【解决方案5】:

    Dart 文档明确指出“避免定义仅包含静态成员的类”。 dart.dev/guides/language/effective-dart/design

    我使用的方法是创建一个或多个文件来存储这些常量。有时,当您的项目太大时,它可能有很多,并且为了加载更少的数据,我更喜欢通过不同的上下文将它们分开,我会使用它们创建单独的文件。 所以我只导入我会使用的那些。

    【讨论】:

    • 在其下方,the documentation 明确表示 “但是,这不是一个硬性规则。对于常量和类似枚举的类型,将它们分组到一个类中可能是很自然的.".
    • @Magnus 是的,但是你可以看到他们放在那里的例子,它是一个类似枚举的类型。这样组织起来更容易,而且你不会实例化它。相反,您只会调用 MyClass.myConstant。但是当你把它变成一个小部件时,你会在内存中使用不必要的空间,而不会得到常量的好处。
    • 我不确定你的意思,我没说小部件?问题是专门询问如何存储常量,以及使用具有静态常量的类 - 例如您的示例 MyClass.myConstant - 将是一个非常好的方法。
    • @Magnus 抱歉,我的回答没有具体说明,我指的是公认的回答方法。我只是想偏离这里接受的答案。投票最多的答案是将所有内容放在一个文件中,我只是说如果您为大型项目放入单独的文件,它会更有条理。但是,当然,当 MyClass.myConstant 以类似枚举的语法变得更有条理时,您可以使用它,特别是如果您可以以一种不会成为代码中更多分心的方式进行操作,以保持可读性。跨度>
    【解决方案6】:

    我喜欢这样组织我的“常量”。我更容易保持井井有条并跟踪已经存在的内容。 我可以做这样的事情:Tables.questions.idTables.anwerOptions.orderIndex

    class Tables {
      static QuestionsTable get questions => QuestionsTable();
      static AnswerOptionsTable get answerOptions => AnswerOptionsTable();
    }
    
    class QuestionsTable {
      String get id => "id";
      String get title => "question";
      String get subtitle => "description";
      String get inputFieldType => "answer_input_type";
      String get answer => "answer";
    }
    
    class AnswerOptionsTable {
      String get id => "id";
      String get questionId => "question_id";
      String get answerOption => "answer_option";
      String get orderIndex => "order_index";
    }
    

    【讨论】:

    • 但是使用这种方法,它们将不是常量,也不会获得常量的好处,导致它使用更多的内存并且必须多做几个步骤才能在每个构建中获取它.
    【解决方案7】:

    参考https://dart.dev/guides/language/effective-dart/design

    在类中分组、常量和类枚举类型是一个很好的做法,如下所示:

    在 Android Studio 中自动导入很简单,您可以在其中输入类名 Color,Android Studio 将能够建议自动导入 Color 类。 p>

    【讨论】:

    • 是的。我的 IDE 无法识别它的事实令人沮丧。无法自动导入并且必须键入“导入”只是暂时没有完成。
    • 我用了最多票,自动完成功能也出现在 Android Studio 中
    【解决方案8】:

    我注意到这里的答案有点混乱,所以我想我会尝试澄清一些事情。

    Dart/Flutter 指南建议不要创建只包含静态成员的类,因为这不是必需的。有些语言,例如 Java 或 C#,不允许你在类之外定义函数、变量或常量,但 Dart 可以。因此,您可以简单地创建一个文件,例如 constants.dart,其中包含您要定义的常量。

    正如@Abhishek Jain 所述,此方法不需要library 关键字即可工作。 library 关键字用于将发布以用于其他项目的库,尽管它可以与 partpart of 一起使用以将单个库分解为多个文件。但是,如果您需要,那么您的需求可能超出了 OP 的问题范围。

    正如@ChinLoong 所指出的,创建一个对相关常量和类枚举类型进行分组的类在技术上是可以接受的。但是应该注意的是,这表明该指南是一个例外,因为它不是硬性规则。虽然这是可能的,但在 Dart 中,不赞成定义一个从不实例化的类。你会注意到定义 Color 常量的 Dart Color 类有一个构造函数,它除了一个整数值,允许实例化不是由常量定义的颜色。

    总之,最符合 Dart 指南的方法是创建一个 constants.dart 文件或一个包含多个不同常量文件的常量文件夹(strings.dartstyles.dart 等)。在 constants.dart 文件中,在顶层定义常量。

    // constants.dart
     
    const String SUCCESS_MESSAGE=" You will be contacted by us very soon.";
    
    ...
    

    然后,import 需要使用常量的文件,并通过常量名称直接访问。

    【讨论】:

      【解决方案9】:

      最佳解决方案是创建一个外部文件,您将在其中创建一个类,然后在其中添加所有常量。

      一个例子:

      constant.dart,你将创建常量类

       import 'package:flutter/material.dart';
           class Constant {
            static Color myColor = Colors.blue;
            static Icon myIcon = Icon(Icons.search , color: Colors.red,);
            static TextStyle myStyle = TextStyle(
              fontSize: 17, 
              fontWeight: FontWeight.bold ,
              color: Colors.green);
          }
      

      我必须将material.dart 导入constant.dart 文件,因为我创建了小部件类型常量。小部件包含在 material.dart 中。如果它只是关于飞镖对象,例如 int , String 等。我不需要它。

      用法:

      Column(
            children: [
                Text('Hello World' ,style: Constant.myStyle,),
                IconButton(icon: Constant.myIcon, onPressed: (){} ),
                Divider(color: Constant.myColor,)
                      ],
                    ),
      

      输出:

      不要忘记导入包含 常量,在我这里是constant.dart

      【讨论】:

        【解决方案10】:

        新建一个名为constants.dart的dart文件,添加如下代码:

        这种方式为您提供带有(context) 或不带(context) 的常量值:

        => 有上下文:

        import 'package:flutter/material.dart';
        
        Color backgroundColor(context) {
          return Theme.of(context).backgroundColor;
        }
        

        => 没有上下文:

        static Color colorB = Colors.blue;
        

        => 用法:

          Container(
            color: backgroundColor(context),
            child: Text('With context'),
          ),
        
        
          //or
        
        
          Container(
            color: colorB,
            child: Text('With context'),
          ),
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-01-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-27
          • 2020-05-09
          • 2022-12-07
          • 2012-06-08
          相关资源
          最近更新 更多