翻译自 https://medium.com/flutter-community/flutter-best-practices-and-tips-7c2782c9ebb5
最佳实践是一个领域内可接受的专业标准,对于任何编程语言来说,提高代码质量、可读性、可维护性和健壮性都非常重要。
这是一些设计和开发 Flutter 应用程序的最佳实践。
命名规范
类名、枚举、typedef、扩展名应该使用大驼峰命名方式
1 2 3 4
| class MainScreen { ... } enum MainItem { .. } typedef Predicate<T> = bool Function(T value); extension MyList<T> on List<T> { ... }
|
libraries、包、目录、源文件名采用蛇形命名。
1 2
| library firebase_dynamic_links; import 'socket/socket_manager.dart';
|
变量、参数等使用蛇形命名
1 2 3 4 5 6
| var item; const bookPrice = 3.14; final urlScheme = RegExp('^([a-z]+):'); void sum(int bookPrice) { }
|
总是指定变量类型
如果已经知道变量值的类型,那么应该指定变量的类型,尽量避免使用var
1 2 3 4 5 6 7 8 9 10 11
| var item = 10; final car = Car(); const timeOut = 2000;
int item = 10; final Car bar = Car(); String name = 'john'; const int timeOut = 20;
|
尽量用is替代as
as运算符会在无法进行类型转换的时候抛出异常,为了避免抛出异常,使用is操作符
1 2 3 4 5 6 7
| (item as Animal).name = 'Lion';
if (item is Animal) item.name = 'Lion';
|
使用??和?.操作符
尽量使用??和?.操作符替代if-null检测
1 2 3 4 5 6 7 8 9 10 11 12
| v = a == null ? b : a;
v = a ?? b;
v = a == null ? null : a.b;
v = a?.b;
|
使用扩散集合(Spread Collections)
当items已经存在另外的集合中时,扩展集合语法可以简化代码
1 2 3 4 5 6 7 8 9
| var y = [4,5,6]; var x = [1,2]; x.addAll(y);
var y = [4,5,6]; var x = [1,2,...y];
|
使用级联操作符
在同一Object上的连续操作可以使用级联操作符..
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var path = Path(); path.lineTo(0, size.height); path.lineTo(size.width, size.height); path.lineTo(size.width, 0); path.close();
var path = Path() ..lineTo(0, size.height) ..lineTo(size.width, size.height) ..lineTo(size.width, 0) ..close();
|
使用原生字符串(Raw Strings)
原生字符串可以不对$和\进行转义
1 2 3 4 5 6
| var s = 'This is demo string \\ and \$';
var s = r'This is demo string \ and $';
|
不要使用null显示初始化变量
dart中的变量默认会被初始化为null,设置初始值为null是多余且不必要的。
1 2 3 4 5 6
| int _item = null;
int _item;
|
使用表达式函数体
对于只有一个表达式的函数,你可以使用表达式函数。=>标记着表达式函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| get width { return right - left; } Widget getProgressBar() { return CircularProgressIndicator( valueColor: AlwaysStoppedAnimation<Color>(Colors.blue), ); }
get width => right - left; Widget getProgressBar() => CircularProgressIndicator( valueColor: AlwaysStoppedAnimation<Color>(Colors.blue), );
|
避免调用print()函数
print()和debugPrint()都用来向控制台打印消息。在print()函数中,如果输出过大,那么Android系统可能会丢弃一些日志。这种情况下,你可以使用debugPrint。
使用插值法来组织字符串
使用插值法组织字符串相对于用+拼接会让字符串更整洁、更短。
1 2 3 4 5 6
| var description = 'Hello, ' + name + '! You are ' + (year - birth).toString() + ' years old.';
var description = 'Hello, $name! You are ${year - birth} years old.';
|
使用async/await而不是滥用future callback
异步代码难以阅读和调试,async和await语法增强了可读性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| Future<int> countActiveUser() { return getActiveUser().then((users) { return users?.length ?? 0;
}).catchError((e) { log.error(e); return 0; }); }
Future<int> countActiveUser() async { try { var users = await getActiveUser(); return users?.length ?? 0; } catch (e) { log.error(e); return 0; } }
|
如果我们把widget定义为const,那么该widget在setState的时候不会重建。通过避免重建来提升性能
1 2 3 4 5 6 7 8 9 10
| Container( padding: const EdgeInsets.only(top: 10), color: Colors.black, child: const Center( child: const Text( "No Data found", style: const TextStyle(fontSize: 30, fontWeight: FontWeight.w800), ), ), );
|