头图

Author/ Kevin Moore & Michael Thomsen

Dart version 2.13 has been released, which adds the type alias function, which is currently the second most popular language feature from users. Dart 2.13 also improves Dart FFI and better performance, and we also provide a new official mirror for Dart. This article will provide you with the latest information about the null security feature introduced in version 2.12, introduce the new features of version 2.13, and the new news about Dart backend support by Docker and Google Cloud. In addition, other changes in subsequent versions will be announced.

empty security update

Dart 2.12 released in March this year, we launched the sound air safety full-featured. Null security is an important feature recently launched by Dart, which aims to help you avoid null value errors (such errors are often difficult to find) and effectively improve work efficiency. We hope that the developers who release the package can follow up the release in time and update the package shared on pub.dev to support air security.

We are extremely pleased to see that in just a few months after the release, air security has been widely adopted. At present, pub.dev, 93% of the packages already support air security. . Here, I would like to express my sincerest gratitude to all package developers who followed up so quickly, and thank you all for helping to push the entire ecosystem forward!

With so many packages supporting air security, you can start to consider migrating your application to an environment that uses air security. To start the migration, first use dart pub outdated check the dependencies of the application. For detailed steps, please refer to Null Security Migration Guide . We have also adjusted the dart create and flutter create templates, and now they enable null security by default in new applications and packages.

launched type alias function

Type alias is version 2.13 of the new language features, but also the majority of developers anticipated features, the feedback has been ranked in the language questions in second . With this feature, developers can create aliases for function types, but cannot create any other types.

With type aliases you can create new names for any existing types, and then use the newly created names wherever the original type can appear. Creating a new name does not really define a new type, it just introduces a short alias. The alias can even pass the type equivalence test:

typedef Integer = int;

void main() {
  print(int == Integer); // true
}

So, how can type aliases be used? A common usage is to assign a shorter or more descriptive name to a type so that your code is easier to understand and maintain.

For example, assigning an alias to the JSON type is a good use (this example was provided by GitHub user Levi-Lesches , thanks hereby). In the following example, we can define a new type alias Json , which describes a JSON document as a map with a key of String and an arbitrary value (using a dynamic type). In this way, when we define fromJson , we can use the Json type alias.

typedef Json = Map<String, dynamic>;

class User {
  final String name;
  final int age;

  User.fromJson(Json json) : 
    name = json['name'],
    age = json['age'];

  Json get json => {
    'name': name, 
    'age': age,
  };
}

You can also call the constructor on the type alias that refers to a certain class. For example, the following example is very compliant:

main() {
  var j = Json();
  j['name'] = 'Michael';
}

By using type aliases to refer to complex types, readers can more easily understand the invariants of your code. For example, the following code defines a type alias to describe a mapping with a key value of generic type X and a value of type List<X> If you assign a name with a single type parameter to the type, the general structure of the mapping will become clearer in the eyes of the code reader.

typedef MapToList<X> = Map<X, List<X>>;
void main() {
  MapToList<int> m = {};
  m[7] = [7]; // OK
  m[8] = [2, 2, 2]; // OK
  for (var x in m.keys) {
    print('$x --> ${m[x]}');
  }
}

=>

7 --> [7]
8 --> [2, 2, 2]

If you try to use a type that does not match, an analysis error will occur:

m[42] = ['The', 'meaning', 'of', 'life']; 


=>

The element type 'String' can't be assigned to the list type 'int'.

You can even use type aliases to rename classes in public libraries. PoorlyNamedClass class in the public library, and you want to rename it to BetterNamedClass . If you just rename the class, your API client will have sudden compilation errors. With type aliases, this problem does not occur. You can rename it at will, but first define a new type alias for the old class name, and then add a few lines of @Deprecated annotations to the old name. In this way, PoorlyNamedClass will be warned, it can still be compiled and run normally, allowing users time to upgrade their code.

mylibrary.dart:

class BetterNamedClass {}

@Deprecated('Use BetterNamedClass instead')
typedef PoorlyNamedClass = BetterNamedClass;

main.dart


import 'mylibrary.dart';


void main() {
  PoorlyNamedClass p;
}

=>

'PoorlyNamedClass' is deprecated and shouldn't be used. Use BetterNamedClass instead.

The following describes how to implement BetterNamedClass and abandon PoorlyNamedClass (in a file named mylibrary.dart ).

class BetterNamedClass {...}

@Deprecated('Use BetterNamedClass instead')
typedef PoorlyNamedClass = BetterNamedClass;

PoorlyNamedClass when trying to use 060b04eab61ce8:

import 'mylibrary.dart';
void main() {
 PoorlyNamedClass p;
}
=>
'PoorlyNamedClass' is deprecated and shouldn't be used. Use BetterNamedClass instead.

The type alias function is available starting from Dart version 2.13. To enable this function, you need to set the lower version of the Dart SDK constraint in your pubspec to the minimum version 2.13, as shown below:

environment:
  sdk: ">=2.13.0 <3.0.0"

This feature supports backward compatibility, thanks to the language version management . In other words, packages with SDK versions lower than 2.13 can safely reference type aliases defined in packages of version 2.13, although packages before version 2.13 cannot define their own type aliases.

Dart 2.13 FFI changes

We have also introduced some new features in Dart FFI (which is an interoperability mechanism for calling C language code).

First, FFI now supports structures containing inline arrays ( #35763 ). Suppose a C language structure has the following inline array:

struct MyStruct {
  uint8_t arr[8];
}

Now, just assign the element type containing a type argument to Array , and the structure can be directly encapsulated in Dart, as shown below:

class StructInlineArray extends Struct {
  @Array(8)
  external Array<Uint8> arr;
}

Secondly, FFI now supports package structure ( #38158 ). Structures are usually placed in memory so that their members located within the address boundary can be more easily accessed by the CPU. When using the package structure , in order to reduce the overall memory footprint, some padding bytes are often ignored in a platform-specific way. With the new @Packed(<alignment>) annotation, you can easily specify padding bytes. For example, the structure created by the following code specifies its byte alignment in memory as 4.

@Packed(4)
class TASKDIALOGCONFIG extends Struct {
  @Uint32()
  external int cbSize;
  @IntPtr()
  external int hwndParent;
  @IntPtr()
  external int hInstance;
  @Uint32()
  external int dwFlags;
…
}

Dart 2.13 performance improvement

We have been constantly working to reduce the application volume and memory footprint of Dart code. In large Flutter applications, the internal structure of the metadata of the Dart program compiled by AOT may take up a considerable amount of memory. Most of these metadata exist to implement functions such as hot reloading, interactive debugging, and formatting readable stack traces, which are never used in applications that need to be deployed. Over the past few years, we have been refactoring the Dart native runtime environment to eliminate this overhead as much as possible. Some of these improvements are applicable to all Flutter applications built in version mode, while some require the use of --split-debug-info split the debugging information in the AOT compiled application, thereby giving up the readable stack trace.

Dart 2.13 has made great progress in memory consumption. When using --split-debug-info , the amount of space occupied by program metadata decreases significantly. For example, the space usage of Flutter Gallery has dropped by 30%: In the --split-debug-info mode, the program metadata takes up 5.7Mb in Dart 2.12, but only 3.7Mb in Dart 2.13. Take the Flutter Gallery application as an example. On the Android platform, the size of the released APK containing debugging information is 112.4MB, and the size without including debugging information is 106.7MB (the total volume is reduced by 5%). The APK contains a lot of resources. Only in terms of the metadata volume inside the APK, it was reduced from 5.7MB on the Dart 2.12 platform to 3.7MB on the Dart 2.13 platform (a reduction of 35%!).

If application volume and memory footprint are more important to you, you can use the --split-debug-info flag to omit debugging information. Please note that once you do this, you need to use the symbolize command to make the stack trace readable again.

Dart official Docker image released and Cloud support

Dart is now available in the official image . Although Dart has already provided Docker images, in order to follow best practices, these new Dart images are tested and verified by Docker. They also support AOT compilation, which can greatly reduce the size of the build container and speed up deployment in a container environment-such as Cloud Run .

Although Dart has always focused on enabling application frameworks such as Flutter to build great interfaces on every screen, we realize that there is at least one hosting service behind most user experiences. By allowing Dart to easily build back-end services to support a full-stack experience, developers can use the same language and business logic as front-end widgets to extend their applications to the cloud.

Generally speaking, using Dart for the back end of Flutter applications is particularly in line with the simplicity and scalability of Google's serverless management platform Cloud Run. This also includes zero scaling, which means that when your backend does not process any requests, there is no cost. We worked with the Google Cloud team to provide Dart's function framework , which is a collection of packages, tools, and examples that enable developers to easily write Dart functions to replace the complete server deployment for processing HTTP requests and CloudEvents.

You can check our Google Cloud official document to get started.

follow-up update notice

In the next version, there will be some exciting changes. As always, you can use the language funnel tracker to keep an eye on our follow-up work.

One area we have been working hard to improve is to define a new set of canonical lints for Dart and Flutter. Lint is static analysis , but because there may be hundreds of lints to enable or disable, sometimes it may be difficult to choose. Right now, we are planning to define two sets of canonical lints to be applied by default in the Dart and Flutter projects. It is expected that these two sets of lint will be enabled by default in the next stable version. If you want to preview in advance, please check the two packages lints and flutter_lints

Finally, if you deeply nest the Dart VM runtime environment, please note that we intend to deprecate its existing mechanism. We will replace it with a faster and more flexible model based on Dart FFI (see tracking issue #45451 ).

Dart version 2.13 is now released

Dart version 2.13 is now available in the Dart 2.13 and Flutter 2.2 SDK. This version adds the type alias function and improves the FFI.

If you have been waiting for the time to migrate your dependencies to an empty safe environment, you may wish to use dart pub outdated to check again. Currently, 93% of the top 500 most popular packages have been migrated. Now may be a good time for you to migrate. Here, I would like to extend my heartfelt thanks to the developers who have migrated!

Welcome to try out the new and improved features introduced in this guide, and tell us your feelings after using them. Please leave a message in the comment area below.


Flutter
350 声望2.5k 粉丝

Flutter 为应用开发带来了革新: 只要一套代码库,即可构建、测试和发布适用于移动、Web、桌面和嵌入式平台的精美应用。Flutter 中文开发者网站 flutter.cn