Flutter 最佳实践

kaichikaichi • 2021-04-14

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.builderListView.builder 会创建一个懒加载列表,当用户滚动列表时,Flutter 会按需加载。

使用 const 声明不需要更新的组件

对于在 setState 调用不需要更新的组件,应将其定义为常量,可以防止不必要的重建,从而提高性能。

Container(
      padding: const EdgeInsets.only(top: 10),
      color: Colors.black,
      child: const Center(
          child: const Text("hello world"),
      ),
);
在 Github 上编辑