“This article has participated in the call for good writing activities, click to view: the back end, the big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!”
Regardless of the programming language, developers need to work on improving code readability, maintainability, robustness, and so on. Flutter also requires some best practices that allow us to write consistent, robust, fast code that is also easy to read and view. Effective Dart provides a detailed guide, but it’s hard to read and remember. This article lists some of the most common examples based on the experience of long-term development.
Naming rules
UpperCamelCase
Big hump nomenclature. Capitalize the first letter of each word.lowerCamelCase
Small hump nomenclature, first word begins with lower case, other words begin with upper case.lowercase_with_underscores
Lowercase underscore nomenclature, all words in lower case, with underscores between words_
The connection.
-
Use small camel name for variables, constants, method names, and parameters. Note that constants are also small camel name:
String name; int phoneNumber = 123456789; const songPrice = 9.99; void sum(int songPrice){ //.... } Copy the code
-
Class names, constructor names, extension class names, definition types, enumerators use big camel names:
extension MyFancyList<T> on List<T> { ... } class Foo { const Foo([Object? arg]); } typedef Predicate<T> = bool Function(T value); enum Status { none, running, stopped, paused } Copy the code
-
Use lowercase underscores for Packages, Libraries, file names, and guide package aliases:
library peg_parser.source_scanner; import 'dart:math' as math; import 'package:angular_components/angular_components' as angular_components; Copy the code
Guide packets using relative paths
To avoid the confusing situation where a project uses both relative and absolute paths, use relative paths in folders. Because the IDE is not that smart, changing the folder name or moving the folder will cause errors in the guide path.
// Don't import 'package:demo/src/utils/dialog_utils.dart'; // Do import '.. /.. /.. /utils/dialog_utils.dart';Copy the code
Specifies a type for a variable that may be null without being initialized to null
Dart supports type inference, but to make it easier to read and know the type at a glance, we need to specify the type:
//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;
Copy the code
For nullable types, there is no need to show that they are initialized to null because the default is null:
// Do
String name;
// Don't
String name = null;
Copy the code
Use operators and cascade operators
Use?? Instead of null-checking the expression, shorten the code:
// Do a = x ?? y; // Don't a = x == null ? y : x; // Do a = x? .y; // Don't a = x == null ? null : x.y; // Do List<String>? strs; if (strs? .isNotEmpty ?? false) { //... } // Don't List<String>? strs; if (strs! =null&&strs.isNotEmpty) { //... }Copy the code
Expand list items using the expand operator:
Var y = [4,5,6]; Var x = y] [1, 2,... Var y = [4,5,6]; Var x = [1, 2]; x.addAll(y);Copy the code
If a series of operations are performed on the same object, a cascading expression should be used:
// Do var path = Path() .. lineTo(0, size.height) .. lineTo(size.width, size.height) .. lineTo(size.width, 0) .. close(); // Don't var path = Path(); path.lineTo(0, size.height); path.lineTo(size.width, size.height); path.lineTo(size.width, 0); path.close();Copy the code
Using lambda expressions:
//Do get width => right - left; Widget getProgressBar() => CircularProgressIndicator( valueColor: AlwaysStoppedAnimation<Color>(Colors.blue), ); //Don't get width { return right - left; } Widget getProgressBar() { return CircularProgressIndicator( valueColor: AlwaysStoppedAnimation<Color>(Colors.blue), ); } //------------------------------------------------------------- List<String> names=[] // Do names.forEach(print); // Don't names.forEach((name) {print(name); });Copy the code
By using raw strings, you can avoid escaping backslashes and dollar signs:
//Do
var s = r'This is demo string \ and $';
//Don't
var s = 'This is demo string \\ and \$';
Copy the code
Building strings with interpolation instead of concatenating strings with + makes strings cleaner and shorter.
// Do var description = 'Hello, $name! You are ${year - birth} years old.'; //Don't var description = 'Hello, '+ name + '! You are ' + (year - birth).toString() + ' years old.';Copy the code
Use the operator is to avoid strong conversions, which may throw an exception if the type is inconsistent:
//Do
if (item is Animal){
item.name = 'Lion';
}
//Don't
(item as Animal).name = 'Lion';
Copy the code
Avoid the use ofprint()
If you print too many logs, Android will discard some of them and print() will leak logs, so use debugPrint(), Dart: Developer: log().
useasync
/await
Processing asynchronous Tasks
Asynchronous code is difficult to read and debug. Async ‘ ‘await syntax improves readability, avoids hellish callbacks and nesting, and makes asynchronous code look like synchronous code:
// Do Future<int> countActiveUser() async { try { var users = await getActiveUser(); return users? .length ?? 0; } catch (e) { log.error(e); return 0; // Don't Future<int> countActiveUser() {return getActiveUser(). Then ((users) {return users? .length ?? 0; }).catchError((e) { log.error(e); return 0; }); }Copy the code
Nested controls with Const and extract
If the control does not need to change state when calling setState, it needs to be declared Const to avoid rebuilding:
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),
),
),
);
Copy the code
If too many nested controls are extracted into separate widgets, do not extract into methods:
The draw method will rebuild, and details from the rendering process illustrate the error that Old Flutter often made — multiple builds
// Do class _NonsenseWidget extends StatelessWidget { const _NonsenseWidget(); @override Widget build(BuildContext context) { return Row( children: < widgets > [Text (' I am the first row), Text (' I am the second line), Text (' I am the third row),],); }} / / Don 't Row _buildRow () {return Row (children: < widgets > [Text (' I am the first Row), Text (' I am the second line), Text (' I am the third Row),],); }Copy the code