Flutter 最佳实践
5 分钟 • 0 阅读
命名规范
类、枚举、typedef 和 extension 名应为大驼峰(UpperCamelCase)。
class HomePage { ... }
enum PageState { ... }
typedef Predicate<T> = bool Function(T value);
extension MyList<T> on List<T> { ... }
库、包、文件夹和文件名应为小写蛇形(lowercase_with_underscores)。
library firebase_dynamic_links;
import 'socket/socket_manager.dart';
变量、常量、参数和命名参数名应为小驼峰(lowerCamelCase)。
var item;
const bookPrice = 3.14;
final urlScheme = RegExp('^([a-z]+):');
void sum(int bookPrice) {
// ...
}
使用相对路径导入文件
在同时使用相对和绝对路径导入时,使用两种方式导入同一类时可能会造成混乱,为了避免这种情况,在 lib/ 下使用相对路径。
// Do
import "../../utils/demo.dart";
// Don`t
import "package:demo/src/utils/demo.dart";
指定值类型
对于知道类型的值,指定其类型,尽可能避免使用 var
。
//Don't
var item = 10;
final car = Car();
const timeOut = 2000;
//Do
int item = 10;
final Car bar = Car();
String name = 'john';
const int timeOut = 20;
使用 is
而不是 as
as
转换类型失败则会抛出异常,为了避免这种情况,应使用 is
判断类型。
//Don't
(item as Animal).name = 'Lion';
//Do
if (item is Animal)
item.name = 'Lion';
使用 if
而不是条件表达式
很多时候我们会根据某些条件去渲染组件,但是如果在某种条件下不需要返回任何组件时应使用 if
。
//Don't
Widget getText(BuildContext context) {
return Row(
children: [
Text("Hello"),
display ? Text("hello") : Container(),
]
);
}
//Do
Widget getText(BuildContext context) {
return Row(
children:
[
Text("Hello"),
if (display) Text("hello")
]
);
}
使用 ??
和 ?.
操作符
使用 ??
和 ?.
操作符,避免空值检查。
//Don't
v = a == null ? b : a;
//Do
v = a ?? b;
// a != null: v = a
// a = null: v = b
//Don't
v = a == null ? null : a.b;
//Do
v = a?.b;
使用 ...
解构
使用 ...
解构让代码看起来更简洁。
//Don't
var y = [4,5,6];
var x = [1,2];
x.addAll(y);
//Do
var y = [4,5,6];
var x = [1,2,...y];
使用 ..
级连运算符
使用 ..
级连运算符对同一对象执行一系列操作。
// Don't
var path = Path();
path.lineTo(0, size.height);
path.lineTo(size.width, size.height);
path.lineTo(size.width, 0);
path.close();
// Do
var path = Path()
..lineTo(0, size.height)
..lineTo(size.width, size.height)
..lineTo(size.width, 0)
..close();
使用原始字符串
原始字符串可以避免转译 \ 和 $
//Don't
var s = 'This is demo string \\ and \$';
//Do
var s = r'This is demo string \ and $';
不要显式初始化变量为 null
在 Dart 中,变量的默认值为 null, 初始化为 null 很多余。
//Don't
int a = null;
//Do
int a;
箭头函数
对于只有一个表达式的函数,推荐使用 =>
。
//Don't
get width {
return right - left;
}
Widget getProgressBar() {
return CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
);
}
//Do
get width => right - left;
Widget getProgressBar() => CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
);
避免使用 print
方法
print()
和 debugPrint()
都用于在控制台输出,如果使用 print()
并且一次输出太多,有时会丢弃输入,为了避免这种情况,建议使用 debugPrint()
。
拆分复杂组件
当 setState
更新状态时,所有的子组件都将重建,为了减少不必要的重建,应将复杂组件拆分为一个个小组件,在小组件内部 setState
更新相应部分。
使用 ListView.builder 构建长列表
当你有一个无限或是非常长的列表时,通常建议使用 ListView
组件来展示。 ListView
会一次构建整个列表。
为了提高性能,避免不必要的资源浪费,推荐使用 ListView.builder
,ListView.builder
会创建一个懒加载列表,当用户滚动列表时,Flutter 会按需加载。
使用 const
声明不需要更新的组件
对于在 setState
调用不需要更新的组件,应将其定义为常量,可以防止不必要的重建,从而提高性能。
Container(
padding: const EdgeInsets.only(top: 10),
color: Colors.black,
child: const Center(
child: const Text("hello world"),
),
);