This article is a translation from the official Dart 2.15 feature introduction article (Announcing Dart 2.15)

An overview of the

Dart 2.15 comes with The release of Flutter 2.8, which is not much of an update but more of a performance optimization. This is good news for developers who don’t have to worry about compatibility issues with the upgrade. For information about Flutter 2.8, read the release of Flutter 2.8 written by De Guo. Read about the new features of Flutter. This article introduces the new features in Dart 2.15.

Using worker Computers to achieve rapid concurrency

Modern devices are equipped with cpus with multiple cores that can perform multiple tasks at once. For most Dart programs, the use of these CPU cores is transparent to the developer — the Dart runtime system runs your Dart code on a single core by default, and then uses other cores to perform system-level tasks, such as asynchronous I/O operations, such as writing files or making network requests.

However, your Dart code itself may need to be run in parallel. For example, you might have a continuous animation and a long task, such as parsing a large JSON file. If the additional task takes too long, the UI may drop frames or lag. By moving these additional tasks to a separate core, the animation can continue to run on the main thread without interruption.

Dart’s concurrency model is based on Computers that are isolated units of execution from other isolations, thereby avoiding concurrency bugs caused by large amounts of concurrent shared memory. The ISOLates in Dart do not allow mutable objects to be shared, but instead share data between different isolates using a messaging mechanism. In Dart version 2.15, a number of significant enhanced updates have been made to Debilitating conditions.

Dart 2.15 redesigns and develops the working mechanism of DEBILITATING networks and introduces a new concept: ISOLATE groups. The ISOLates in the same ISOLATE group can share a large amount of internal data when applications are running within the group. This makes the cost of independent isolates within the group much lower. For existing ISOLATE groups, starting a new ISOLATE was 100 times faster because we no longer needed to initialize the program structure, and the newly created ISOLATE consumed 1/10, or even 1/100, of the memory of the old one.

At the same time, isolate groups still do not allow different isolate groups to share mutable objects. The ISOLATE Groups are implemented using a shared heap, which allows for better compatibility later on. We can pass objects from one ISOLATE to another, which can be used for worker ISOLATE tasks that return large chunks of memory data. For example, a Worker ISOLATE takes data through network calls, parses the data into a large JSON object, and passes this JSON object to the Main ISOLATE. Prior to Dart 2.15, deep copies of returned results were required, which could cause UI stuttering if the copy took longer than the frame rendering load.

In Dart version 2.15, the Worker ISOLATE can call the isolate.exit () method with its result as an argument. The Dart runtime then passes the memory containing the changes from the Worker ISOLATE to the Main ISOLATE without copying. The compute() method has been updated in Flutter 2.8 to take advantage of this isolate.exit () advantage. If the compute() method is used in Flutter 2.8, upgrading to Flutter 2.8 automatically gains this performance improvement from the worker isolate.

Finally, Dart rewrote the messaging mechanism of ISOLATE to deliver small to medium sized messages nearly eight times faster. Sending a message is especially obvious, and receiving a message is basically done in a certain amount of time. The types of objects passed between computers have also been extended to include functions, closures, and StackTrace. For more information, see the API documentation for the sendPort.send () method.

Documentation on how to use Dart version 2.15 is available and sample code is provided.

New language feature: Constructor tear-offs

The term Constructor tear-offs is a bit difficult to translate, meaning that in a program we can refer to an object’s methods as objects for assignment or as arguments. Here’s an example:

class Greeter {
  final String name;
  Greeter(this.name);
  
  void greet(String who) {
    print('$name says: Hello $who! '); }}void main() {
  final m = Greeter('Michael');
  final g = m.greet; // g holds a function pointer to m.greet.
  g('Leaf'); // Invokes and prints "Michael says: Hello Leaf!"
}
Copy the code

G refers to the greet method on m, and then g is a pointer to the greet function. This approach is common in Dart’s core library, such as the forEach method that passes the greet method on the M object above to the array.

final m = Greeter('Michael');
['Lasse'.'Bob'.'Erik'].forEach(m.greet);
// Prints "Michael says: Hello Lasse!" , "Michael says: Hello Bob!" .
// "Michael says: Hello Erik!"
Copy the code

The tear-off form for constructors was not previously supported, but is actually required for Flutter construction purposes. Dart version 2.15 supports this feature, and the following code builds a Column component that contains multiple Text components, which can be built using the tear-off form of Text in the Map method.

class FruitWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
        children: ['Apple'.'Orange'].map(Text.new).toList()); }}Copy the code

Text.new references the default constructor of Text. You can also use named constructors, such as.map(text.rich).

Tear-off related changes

For function Pointers, Dart updates some of the syntax to maintain consistency. You can now use special generic methods to create non-generic methods.

T id<T>(T value) => value;
var intId = id<int>; // 2.15 New syntax
int Function(int) intId = id; // Prior to 2.15
Copy the code

It is even possible to create a non-generic function object using a generic function object:

const fo = id; // Create a function object with an ID
const c1 = fo<int>; // Version 2.15 is available. The previous version reported an error
Copy the code

Also, you can omit the type for generics.

var y = List; // Version 2.15 supports
var z = List<int>; // Version 2.15 supports
var z = typeOf<List<int> > ();// Versions prior to 2.15
Copy the code

Improved enumeration of the Dart core library

Now we can use the.name attribute to get the string value for the enumeration.

enum MyEnum {
  one, two, three
}
void main() {
  print(MyEnum.one.name);  // Prints "one".
}
Copy the code

You can also build enumeration objects using.byname:

print(MyEnum.values.byName('two') == MyEnum.two);  // Prints "true".
Copy the code

It is also possible to map a collection of enumerated values to a map.

final map = MyEnum.values.asNameMap(); 
print(map['three'] == MyEnum.three);  // Prints "true".
Copy the code

Compression pointer

Dart 2.15 uses compressed pointer technology for Pointers that only need to support 32-bit address Spaces to improve the space footprint of such Pointers in the 64-bit SDK. In this way, nearly 10% of the Dart heap space was saved in internally tested applications. This feature is an optional configuration option for embedded developers. Flutter 2.8 has this feature enabled by default for Android and will be supported for iOS in a later version.

Other features

Other features are less relevant to development and are listed below:

  • Dart DevTools is included with the Dart SDK, eliminating the need for a separate download and installation.
  • Added a new pub feature to the plugin release: this is mainly for security checks, such as if you wrote your personal key in the plugin, it will prompt you before release and stop the release. For example, give the following warning:
Publishing my_package 1.0.0 to https://pub.dartlang.org: Package validation found the following errors: * line 1, column 1 of lib/key.pem: Potential leak of Private Key detected. ╷ 1 │ chrysene -BEGIN Private Key - 2 │ 53 WMSN H0M6xpM2q + / 3 │ eYLdgtjgBd3DBmHtPilCkiFICXyaA8z9LkJ └ - END PRIVATE KEY - ╵ * line 2, column 23 of lib/my_package.dart: Potential leak of Google OAuth Refresh Token detected. ╷ 2 │ Final refreshToken = "1//042ys8uoFwZrkCgYIARAAGAQSNwF-L9IrXmFYE-sfKefSpoCnyqEcsHX97Y90KY-p8TPYPPnY2IPgRXdy0QeVw7URuF5u9oUeIF0";Copy the code

False_secrets This detection can fail and can be turned off using whitelists which omit certain files as per: false_secrets. In addition, it provides a recall function for plug-in publishing, which can be operated in the management background interface of pub.dev. When the version is withdrawn, the pub client no longer resolves this version when performing pub GET or PUB Update. In the pubspec.lock file, you will see the corresponding prompt.

$ dart pub getResolving dependencies... Mypkg 0.0.181-buggy (retracted, 0.0.182-fixed available) Got dependencies!Copy the code
  • This is a bug that may occur with some character sets, as in the following example:
main() { final accessLevel = 'user'; If (accessLevel == 'user‮.⁦// Check if admin⁩ ⁦') {print('You are a regular user.'); } else { print('You are an admin.'); }}Copy the code

In fact, in some character sets, the above program prints ‘You are an admin. ‘This can be problematic when using bidirectional Unicode character sets. If one character is from left to right and one is from right to left then strings that look the same are actually not equal. The Dart analysis tool provides this type of detection:

$ dart analyze
Analyzing cvetest...                   2.6s
info • bin/cvetest.dart:4:27 • The Unicode code point 'U+202E'
       changes the appearance of text from how it's interpreted
       by the compiler. Try removing the code point or using the 
       Unicode escape sequence '\u202E'. •
       text_direction_code_point_in_literal
Copy the code

2022 message

This is the final Dart update for 2021, and we are grateful to the members who have been involved in building the Dart ecosystem. Thank you to everyone who provided great feedback, your continued support gives us the momentum to continue to move forward and grow. The thousands of plug-ins published on Pub.dev help us complete the Dart ecosystem. We have a lot of exciting events planned for 2022, and we can’t wait for next year!

Personal feelings

It feels like the Dart language itself has matured, and the changes in the release update are less about underlying performance improvements, toolchain improvements, and a more user-friendly experience. 2022 is likely to be the year that Flutter comes of age on both the Web and desktop side. Look forward to the release of Flutter 3.0 in THE first quarter of 2022.