9/12/2021 vừa qua, team Flutter và team phát triển ngôn ngữ Dart thông báo cập nhật phiên bản mới. Ở bài viết này, chúng ta sẽ cùng nhau tìm hiểu chi tiết những tính năng vừa mới được cập nhật thêm ở phiên bản Dart 2.15. Cùng xem thử để xem có tính năng nào mà bạn đang "mong chờ" từ lâu đối với ngôn ngữ Dart hay không 😄.
Tóm tắt nhanh các tính năng nổi bật bao gồm:
- Thêm phương thức khai báo constructor kiểu mới: tear-off.
- Improve cách sử dụng kiểu enum với thư viện dart:core.
- Thêm các tính năng mới hỗ trợ các publisher quản lý các package của mình trên Pub.dev.
1. Fast Concurrency với worker isolates
Các thiết bị hiện đại hiện nay với sự hỗ trợ rất nhiều từ những CPU siêu mạnh chứa nhiều core có thể chạy song song nhiều thread và tác vụ ngầm cùng một lúc. Đối với các chương trình được thực thi từ ngôn ngữ Dart, mặc định Dart runtime system sẽ chạy tất cả các code Dart trên 1 single core, sau đó ngôn ngữ có thể sử dụng thêm các core khác để thực hiện các tác vụ cấp bậc hệ thống (system level) như chạy async xử lý các input/output, call api, download file, v.v
Nhưng thông thường ứng dụng Flutter của bạn phải đồng thời chạy thực thi nhiều tác vụ cùng 1 lúc, chẳng hạn như bạn vào 1 màn hình bất kỳ. Khi vào màn hình đó, bạn cho Animation trong màn hình bắt đầu chuyển động nhưng đồng thời call api parse json lấy dữ liệu để hiện thì lên màn hình (tạm gọi việc này là tác vụ thêm). Nếu việc xử lý dữ liệu quá lâu, nó có thể dẫn đến làm lag UI hoặc tệ hơn là làm Animation chạy "giựt giựt" gây trải nghiệm không tốt với người dùng. Nếu bạn biết cách "moving" các tác vụ thêm của mình chạy trên 1 core tách biệt, Animation của bạn sẽ tiếp tục chạy trên main thread mà không phải bị những thứ khác làm phiền, đương nhiên điều này sẽ làm cho ứng dụng của bạn chạy Animation lúc nào cũng mượt mà cả 😄.
Concurrency của Dart dựa trên mô hình isolates - một đơn vị độc lập thực thi chương trình ở một nơi riêng biệt. Ở phiên bản 2.15, Dart đã thực hiện nhiều nâng cấp cho các isolates.
Team Dart bắt đầu bằng việc re-design và re-implement lại cách hoạt động của isolates bằng cách giới thiệu 1 khái niệm mới: isolate groups. Các isolate trong isolate group chia sẻ các cấu trúc internal data đại diện cho chương trình đang chạy. Điều này giúp cho chương trình của bạn chạy nhanh hơn 100 lần trong việc thêm mới 1 isolate vào group isolate hiện có bởi vì chương trình không cần phải khởi tạo lại cấu trúc data và chi phí bộ nhớ sử dụng cho isolate này giảm từ 10 đến 100 lần.
Chúng ta có thể truyền object từ isolate này sang isolate khác, nó có thể được sử dụng cho các worker isolate hoạt động khi chương trình cần phải thực hiện các tác vụ cần nhiều memory. Một ví dụ điển hình thường gặp khi sử dụng worker isolate là khi bạn call api để lấy dữ liệu, sau đó bạn parse cục data đó thành 1 object JSON Graph và object đó được đưa về cho main isolate. Ở các phiên bản trước Dart 2.15, các kết quả mà bạn nhận được phải thực hiện nghiệp vụ deep-copied, điều đó có thể làm cho UI của ứng dụng bị jank và giựt lag vì việc copy tiêu tốn nhiều chi phí để thực hiện.
Ở phiên bản này, các worker isolate có thể gọi hàm Isolate.exit()
để truyền các các kết quả sau khi thực hiện xong thành các argument. Sau đó, Dart Runtime sẽ truyền các bộ nhớ chứa kết quả từ worker isolate sang main isolate mà không cần phải copy, và đặc biệt hơn là main isolate nhận được kết quả ngay tức thì. Team Dart đã cập nhật lại chức năng cho hàm compute()
cho Flutter version 2.8 để có thể nhận được full sức mạnh từ bản cập nhật mới. Nếu bạn đang sử dụng hàm compute()
, bạn sẽ thấy được sự khác biệt rõ rệt sau khi cập nhật Flutter lên phiên bản 2.8
Cuối cùng, Dart đã rework lại cơ chế "giao tiếp" của isolate. Việc làm lại này giúp cho việc chuyển đi các message có kích cỡ từ nhỏ đến vừa nhanh hơn gấp 8 lần. Và đặc biệt hơn là ở đầu nhận lúc nào cũng nhận được ở constant time. Ngoài ra, Dart giờ đây hỗ trợ việc truyền các "message" đa dạng hơn như bạn có thể truyền function types, closures, hoặc stacktrace object. Xem chi tiết tại đây.
Và để dễ dàng hơn trong việc tìm hiểu và sử dụng isolates, mọi người có thể xem thêm document về Concurreny trong Dart và cũng như tự tay làm các ví dụ ở link này.
2. Constructor tear-offs
Bạn có thể khởi tạo 1 function object, nó sẽ tham chiếu đến 1 function object khác, bằng cách sử dụng function name. Trong ví dụ ở dưới đây, dòng thứ hai trong hàm main()
là cách bạn sử dụng chức năng trên khi bạn có thể tham chiếu g
với m.greet
.
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!"
}
Tương tự như pointer function, tear-off function cũng xuất hiện rất nhiều khi bạn sử dụng ngôn ngữ Dart. Dưới đây là 1 ví dụ khi sử dụng kết hợp function foreach()
để duyệt qua các phần tử và pointer function.
final m = Greeter('Michael');
['Lasse', 'Bob', 'Erik'].forEach(m.greet);
// Prints "Michael says: Hello Lasse!", "Michael says: Hello Bob!",
// "Michael says: Hello Erik!"
Trước đây, trong một số trường hợp khi dựng layout với Flutter UI bạn sẽ thấy khá khó chịu vì ngôn ngữ Dart chưa support tear-off function. Nhưng kể từ Flutter 2.8 trở đi, khi bạn muốn xây dựng layout list Column Text, bạn có thể dễ dàng code như sau:
class FruitWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: ['Apple', 'Orange'].map(Text.new).toList(),
);
}
}
Text.new
refer đến hàm constructor mặc định của Text widget.
3. Một vài thay đổi khác
Trong lúc thực hiện contrucstor tear-off, team phát triển ngôn ngữ Dart nhận thấy có một vài vấn đề liên quan đến việc không đồng nhất được syntak hỗ trợ cho chức năng trên. Do đó, team đã có một vài điều chỉnh để nhất quán hơn như sau:
T id<T>(T value) => value;
var intId = id<int>; // New in 2.15.
int Function(int) intId = id; // Pre-2.15 workaround.
Ngoài ra, bạn còn có thể sử dụng generic function để khởi tạo non-generic function:
const fo = id; // Tear off `id`, creating a function object.
const c1 = fo<int>; // New in 2.15; error before.
Một thay đổi khác đó là syntak code để bạn define kiểu literals.
var y = List; // Already supported.
var z = List<int>; // New in 2.15.
var z = typeOf<List<int>>(); // Pre-2.15 workaround.
4. Improve enum trong thư viện dart:core
Giờ đây bạn đã có thể get được kiểu dữ liệu String đối với biến enum (I like it :v) bằng cách sau:
enum MyEnum {
one, two, three
}
void main() {
print(MyEnum.one.name); // Prints "one".
}
Ngoài ra, bạn có thể look up giá trị enum từ kiểu dữ liệu String bằng cách:
print(MyEnum.values.byName('two') == MyEnum.two); // Prints "true".
Cuối cùng, bạn có thể mapping qua lại giữa cặp giá trị enum & String.
final map = MyEnum.values.asNameMap();
print(map['three'] == MyEnum.three); // Prints "true".
Bạn có thể tham khảo cách sử dụng ở link đây.
5. DartDevTools được thêm vào DartSDK luôn
Trước đây, công cụ hỗ trợ trong việc debug và theo dõi performance ứng dụng không nằm trong DartSDK. Nếu bạn muốn sử dụng, bạn phải tự download riêng. Nhưng ở thời điểm hiện tại, khi bạn download DartSDK, DartDevTools đã được tải chung với bộ DartSDK. Để tìm hiểu chi tiết cách sử DevTools với Dart command line, bạn có thể đọc thêm DevTools documentation.
6. Tính năng mới trên pub hỗ trợ cho các publisher
Tính năng mới đầu tiên được Dart 2.15 SDK thêm vào đó là security feature. Mục đích của tính năng này đó là giúp cho các publisher bảo vệ được các thông tin cá nhân, tránh việc sơ suất để lộ các thông tin nhạy cảm như keyAPI, cloud, credential,.. trước khi publish package lên trang Pub.dev
Mỗi ngày, có hàng nghìn thông tin bị leak trên Github và team phát triển ngôn ngữ Dart không muốn điều này xảy ra đối với bạn sau khi tìm hiểu và đọc được tài liệu này
Tính năng leak detection được thêm vào bên trong câu lệnh chạy pre-publish dart pub publish
- giúp bạn validation lại mọi thứ. Nếu phát hiện ra các thông tin "bảo mật", chương trình sẽ không cho bạn publish và văng ra các warning message để bạn kiểm tra lại, ví dụ như:
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 │ ┌ - - -BEGIN PRIVATE KEY - - -
2 │ │ H0M6xpM2q+53wmsN/eYLdgtjgBd3DBmHtPilCkiFICXyaA8z9LkJ
3 │ └ - - -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";
Trong trường hợp bạn muốn publish luôn các thông tin như private key chẳng hạn, bạn có thể khai báo file đó vào danh sách allowlist để chương trình bỏ qua.
Cập nhật tiếp theo đó là cho phép bạn loại bỏ các version bị lỗi đã publish trên trang Pub. Giả sử bạn vừa thêm mới 1 tính năng cho package của mình, sau khi publish nhưng bạn kiểm tra lại thì nó bị lỗi hoặc chạy không như mong muốn của bạn, thay vì trước đây phải cố gắng fix nhanh nhất có thể để cho những ai sử dụng package của bạn không gặp phải thì giờ đây bạn chỉ cần lên trang Admin của Pub và loại bỏ nó đi một cách nhẹ nhàng.

Tất nhiên sau khi bạn loại bỏ version đó đi, bạn sẽ thấy trong file pubspec.lock
hiển thị câu warning message như sau khi chạy pub get
:
$ dart pub get
Resolving dependencies…
mypkg 0.0.181-buggy (retracted, 0.0.182-fixed available)
Got dependencies!
Tóm lại
Theo quan điểm của mình (người viết), Dart 2.15 đã cập nhật rất nhiều các tính năng thú vị, có cả cái mình đang rất mong đợi đó là chuyển enum sang String. Giờ cũng là thời điểm cuối năm 2021 và mình tin rằng năm sau sẽ còn là một năm bùng nổ nữa của Flutter cũng như ngôn ngữ Dart. Cảm ơn bạn đã dành thời gian đọc bài viết này ^^.
Xem thêm bài viết gốc ở link đây.

Tùng Đường
Sao bạn có thể bước chân lên sân khấu, khi còn chẳng có sức kéo bản thân ra khỏi giường hả homie?
follow me :
Bài viết liên quan
10 Dart Array Methods trong Flutter bạn cần biết
Sep 02, 2023 • 6 min read
Tự học Dart: Các Dart Operators (toán tử) bạn cần biết
Sep 02, 2023 • 18 min read
Dart là gì? Giới thiệu cơ bản về ngôn ngữ lập trình Dart
Aug 21, 2023 • 11 min read
Flutter Tutorial 2022: Giới thiệu Flutter Travel App
Sep 07, 2022 • 3 min read
Tổng hợp các Shortcuts, Extensions & Settings trong VSCode khi lập trình Flutter
Jun 03, 2022 • 10 min read
[Phần 1] Những extension cần thiết khi làm việc với Flutter trên VS Code
May 27, 2022 • 4 min read