Flutter 开发中的最佳实践

Flutter 开发的注意事项,大量参考了 android-best-practices

总结

从头开始开发应用时,首先添加 linting 规则

尽可能使用 const

创建单独的类来定义颜色

为您的应用定义主题

不要使用函数式小部件


lint 规则

每当您从头开始一个项目时,首先添加 Lint 包,它可以帮助您静态分析 flutter/dart 代码,并帮助您提高代码质量,从而最终减少 bug 和错误。

使用 const

尽可能尝试使用 const 关键字,以提高应用的性能。例如:当您将它用于某些小部件时,当调用 setState 时,它不会更改带有 const 关键字的 widget

const Text(
  "Flutter Best Practices",
  style: const TextStyle(
    fontSize: 24,
    fontWeight: FontWeight.bold,
  ),
),

单独的颜色类

尝试将您应用程序的所有颜色放在一个类中,如果不是使用本地化,也同样用于字符串,这样当您想添加本地化时,就可以在一个地方找到所有字符串。

注意:您可能会遇到 linting 错误 avoid_classes_with_only_static_members,但对于这种用法可以忽略。

引用官方 文档

在惯用的 Dart 中,类定义了对象的种类。永不实例化的类型是一种代码异味。
但是,这不是硬性规定。对于常量和类似枚举的类型,将它们分组到一个类中可能是很自然的。

颜色示例

class AppColor {
  static const Color red = Color(0xFFFF0000);
  static const Color green = Color(0xFF4CAF50);
  static const Color errorRed = Color(0xFFFF6E6E);
}

定义主题

优先定义应用的主题,以避免在未来的更新中更改主题的麻烦。设置主题肯定会令人困惑,但这是一次性的任务。
请您的设计师分享所有与主题相关的数据,例如颜色、字体大小和字重。

示例

MaterialApp(
  title: appName,
  theme: ThemeData(
    // Define the default brightness and colors.
    brightness: Brightness.dark,
    
    // You can add the color from the seprate class here as well to maintain it well.
    primaryColor: Colors.lightBlue[800],

    // Define the default font family.
    fontFamily: 'Georgia',

    // Define the default `TextTheme`. Use this to specify the default
    // text styling for headlines, titles, bodies of text, and more.
    textTheme: const TextTheme(
      headline1: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold),
      headline6: TextStyle(fontSize: 36.0, fontStyle: FontStyle.italic),
      bodyText2: TextStyle(fontSize: 14.0, fontFamily: 'Hind'),
    ),
  ),
  home: const MyHomePage(
    title: appName,
  ),
);

您可以通过主题做更多事情,例如一次性定义您的自定义 TextField、Card、Bottom Navigation Bar 主题,并在应用中直接使用。在此处查看使用 Theme 的示例:此处

此外,在一个大型应用/项目中,您可能最终会有多个主题,不仅仅是浅色和深色模式主题,还有一些特定小部件/组件的自定义主题,所以您可以创建一个单独的类/文件并在那里维护所有主题。

避免函数式小部件

我们通常会遇到需要将 UI 代码从小部件中分离出来的情况,但我们避免创建新的小部件,而是使用返回 Widget 的函数。
这种做法有一些好处,例如您不需要将所有参数传递给新小部件,代码更少,文件也更少。但当您想检查小部件时,这种方法可能会导致问题。让我们深入了解一下。

当您使用函数式小部件时,代码看起来是这样的。

Widget functionWidget({ Widget child}) {
  return Container(child: child);
}

您现在可以这样使用它:

functionWidget(
  child: functionWidget(),
);

在这种情况下,Widget 树看起来是这样的:

Container
  Container

相反,如果我们使用 Widget,我们的 Widget 看起来是这样的:

class ClassWidget extends StatelessWidget {
  final Widget child;

  const ClassWidget({Key key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: child,
    );
  }
}

您可以这样使用它:

new ClassWidget(
  child: new ClassWidget(),
);

在这种情况下,Widget 树看起来是这样的:

ClassWidget
  Container
    ClassWidget
      Container

正如我们在这里看到的,如果我们使用 Widget,框架会更好地理解它,UI 也更容易检查。
有关更多信息,请参考 Stack Overflow 的 这个 回答

GitHub

查看 Github