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 的 这个 回答