来源:Kinjal Dhamat
https://medium.com/flutter-community/flutter-best-practices-and-tips-7c2782c9ebb5
最佳实践是一个领域可以接受的专业标准,对于任何编程语言来说,提高代码质量、可读性、可维护性和健壮性都非常重要。
让我们探索一些设计和开发Flutter应用程序的最佳实践。
class 、 enum 、 typedef 和 extension 应采用驼峰命名 UpperCamelCase 规则。
class MainScreen { ... } enum MainItem { .. } 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/ 文件夹中的文件使用相对路径导入
// Don't import 'package:demo/src/utils/dialog_utils.dart'; // Do import '../../../utils/dialog_utils.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;通常,如果无法进行强制转换,使用 as 强制转换将会引发异常,为了避免异常,可以使用 is
//Don't (item as Animal).name = 'Lion'; //Do if (item is Animal) item.name = 'Lion';很多时候,我们需要根据条件渲染 Widget ,如果在条件表达式在任何情况下都返回 null 时,那么我们应该仅仅使用 if 条件
//Don't Widget getText(BuildContext context) { return Row( children: [ Text("Hello"), Platform.isAndroid ? Text("Android") : null, Platform.isAndroid ? Text("Android") : SizeBox(), Platform.isAndroid ? Text("Android") : Container(), ] ); } //Do Widget getText(BuildContext context) { return Row( children: [ Text("Hello"), if (Platform.isAndroid) Text("Android") ] ); }优先使用 ?? (如果为 null ) 和 ?. (可识别空值)运算符,而不是条件表达式中 null 检查
//Don't v = a == null ? b : a; //Do v = a ?? b; //Don't v = a == null ? null : a.b; //Do v = a?.b;当现有项目已经存储在另一个集合中时,spread 集合语法将使代码更简单
//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 $';在 Dart 中,如果未指定变量的值,则变量会自动初始化为 null ,因此添加 null 是多余且不需要的
//Don't int _item = null; //Do int _item;对于仅包含一个表达式的函数,可以使用表达式函数
//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() 和 debugPrint() 均用于打印日志到控制台,如果你使用 print() 并且一次输出太多内容,Android 有时会丢弃一些日志行,为了避免这种情况,请使用 debugPrint()
当调用 setState() ,所有后代 Widget 都将重建,因此,将 Widget 拆分为小的 Widget ,在真正需要改变的 Widget 上调用 setState()
Scaffold( appBar: CustomAppBar(title: "Verify Code"), // Sub Widget body: Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ TimerView( // Sub Widget key: _timerKey, resendClick: () {}) ], ), ), )当使用无限列表或者非常大的列表时,通常建议使用 ListView.builder 以提高性能。
默认的 ListView 构造函数一次生成整个列表,ListView.builder 创建一个惰性列表,当用户向下滚动列表时,Flutter 会按需构建 Widget
当 setState 调用时不会改变的 Widget ,我们应该将其定义为常量,这将阻止 Widget 重建,从而提高性能
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), ), ), );我希望这些能给你一些见识,使你的 Flutter 代码更具可读性,同时也可以提高应用程序的性能。
编码愉快!
欢迎关注「前端瓶子君」,回复「交流」加入前端交流群!
回复「算法」,你可以每天学习一道大厂算法编程题(阿里、腾讯、百度、字节等等)或 leetcode,瓶子君都会在第二天解答哟!
另外,每周还有手写源码题,瓶子君也会解答哟!
》》面试官也在看的算法资料《《
“在看和转发”就是最大的支持