Expand operators (Spread Operators)
The expansion operator… The ability to insert elements from list, set, map literals into a collection. Whether an object can be expanded depends on whether Iterable is inherited, except for the Map collection, where expanding a Map actually calls entries.iterator() of the Map
In real development, we might need to create a new collection, the elements of which usually depend on another existing collection, and then add new elements to the base again, such as:
var args = testArgs.toList() .. add('--packages=${PackageMap.globalPackagesPath}')
..add('-rexpanded')
..addAll(filePaths);
Copy the code
The above code case, from the official website. The toList() function creates a new collection containing all the elements of testArgs, simplifies the code by making chained calls through the cascade operator, and finally adds all the elements of another collection through addAll
But this is still very cumbersome, so here’s how to simplify the code by using the expansion operator:
Var args = [...testArgs, // by expanding the operator willtestThe Args collection is unpacked and the elements inside are put into Args one by one'--packages=${PackageMap.globalPackagesPath}'.'-rexpanded'. FilePaths // Unpack the filePaths with the expansion operator and put the items in args one by one];Copy the code
Declarative UI is used for Flutter, and imperative style is used for Android/iOS.
What is declarative UI? In a Flutter, if a Widget changes, triggered by the setState function, then the Flutter builds a new Widget instance and Widget subtree. The imperative UI takes the original Widget instance, The instance’s methods are then called to trigger the change rather than creating a new Widget
The code style differences between them are as follows:
// Declarative UI code stylereturnViewB( color: red, child: ViewC(...) ,) // Imperative UI code style b.setColor(red) b.clearChildren() ViewC c3 = new ViewC(...) b.add(c3)Copy the code
The expand operator is widely used in a declarative UI like Flutter. For example, we build a ListView:
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: ListView(
children: [ //children 就是一个List
Tab2Header(),
// buildTab2Conversation()返回值也是一个List
...buildTab2Conversation(),
],
),
);
}
Copy the code
The above example uses the expansion operator in a List and in a Map collection, as well, such as combining queryParams and formParams to create a new Map collection
var map = { ... options.queryParameters, ... options.data };Copy the code
The same goes for using the expansion operator in a Set, as in:
var items = [2, 3, 4];
var set= {1, 2... items };Copy the code
Null-aware spread operator (null-aware spread)
The expansion operator mentioned above throws a runtime exception if the expanded object is null
var oops = null;
//NoSuchMethodError: The getter 'iterator' was called on null
var list = [...oops];
Copy the code
If the expanded object may be null, we need to add? To the expansion operator. No. (… ?). :
var oops = null;
var list = [...?oops];
Copy the code
Expand operator semantic analysis
List uses the expansion operator for analysis
var list = [elem_1 ... elem_n] 1. Iterates over all elements in the literal1) assigns the element expression (expansion operator) to value iterates 2) if the iterated element is the expansion operator a) if the nullable expansion operator is used and value is null, directlycontinueIterator c) then iterate over the iterator to append the elements to the collection created above. 3) If the iterator is not an expansion operator, add the elements directly to the collection. In this way, the elements of the collection literal are all in the new collection aboveCopy the code
Other collections such as sets and maps have similar mechanisms
Control Flow Collections
Collection-if /for is a collection of control flow statements that can be used when building collection literals
We mentioned above that Flutter is a declarative UI, for example:
Widget build(BuildContext context) {
returnRow(children: [// Set literals IconButton(icon: icon (icon.menu)), Expanded(Child: title), IconButton(icon: Icon(Icons.search)), ], ); }Copy the code
If we wanted to add some judgment to the code above, such as displaying the icons.search button only on Android, we might write:
Widget build(BuildContext context) {var buttons = <Widget>[IconButton(icon: Icon(Icons.menu)), Expanded(child: title), ]; // For Android, add a search buttonif (isAndroid) {
buttons.add(IconButton(icon: Icon(Icons.search)));
}
return Row(
children: buttons,
);
}
Copy the code
With Control Flow Collection, we can simplify the code by using this class:
Widget build(BuildContext context) {
returnRow(children: [IconButton(icon: icon (Icons. Menu)), Expanded(Child: title), // If android, add the search buttonif (isAndroid) IconButton(icon: Icon(Icons.search)),
]
);
}
Copy the code
In addition to using if, you can also use else, for example to show the search button on Android, and other platforms to show about the button:
Widget build(BuildContext context) {
return Row(
children: [
IconButton(icon: Icon(Icons.menu)),
Expanded(child: title),
if (isAndroid)
IconButton(icon: Icon(Icons.search))
else
IconButton(icon: Icon(Icons.about)),
]
);
}
Copy the code
For example, if we need to generate another set from one set, we might write:
var command = [
engineDartPath,
frontendServer,
];
for (var root in fileSystemRoots) {
command.add('--filesystem-root=$root');
}
for (var entryPointsJson in entryPointsJsonFiles) {
if (fileExists("$entryPointsJson.json")) {
command.add(entryPointsJson);
}
}
command.add(mainPath);
Copy the code
With Control Flow Collection, we can write this for more readability:
var command = [
engineDartPath,
frontendServer,
for (var root in fileSystemRoots) '--filesystem-root=$root'.for (var entryPointsJson in entryPointsJsonFiles)
if (fileExists("$entryPointsJson.json")) entryPointsJson,
mainPath
];
Copy the code
The for loop can also be evaluated while building a collection literal:
var integers = [for (var i = 1; i < 5; i++) i]; // [1, 2, 3, 4]
var squares = [for (var n in integers) n * n]; // [1, 4, 9, 16]
Copy the code
When building a Map literal, we might write:
Map<String, WidgetBuilder>.fromIterable(
kAllGalleryDemos,
key: (demo) => '${demo.routeName}',
value: (demo) => demo.buildRoute,
);
Copy the code
Collection-for simplifies our code to something like this:
return {
for (var demo in kAllGalleryDemos)
'${demo.routeName}': demo.buildRoute,
};
Copy the code
Collection if-for can also be combined, such as for loop nesting, for-if nesting:
//for-for
[for (var x in hor) for (var y in vert) Point(x, y)]
//for-if
[for (var i in integers) if (i.isEven) i * i]
Copy the code
conclusion
Dart expansion operators (null-aware spread, non-null-ware spread) and Control flow collections(Collection if/for)
Let’s make our code more readable when we write it
In particular, the writing of Flutter UI is more in line with the declarative style code style
As you can see, the Dart code is very expressive
Reference
So much for the Dart expansion operator and Control Flow Collections. For more information about Android, check out my GitHub: github.com/chiclaim/An…
Flutter. Dev/docs/get – st… Github.com/dart-lang/l… Github.com/dart-lang/l…
To contact me
The following is my public number, dry goods articles not bad, there is a need to pay attention to, there are any questions can contact me: