Dart là ngôn ngữ lập trình chính được sử dụng trong Flutter – một framework phổ biến để phát triển ứng dụng di động đa nền tảng. Với cú pháp hiện đại, linh hoạt và hiệu suất cao, Dart cung cấp nền tảng vững chắc để xây dựng các ứng dụng có giao diện đẹp, hiệu năng mượt mà và khả năng mở rộng cao. Bài viết này sẽ giới thiệu tổng quan về vai trò của Dart trong Flutter, các tính năng nổi bật và lý do vì sao Dart Flutter lại là “cặp bài trùng” lý tưởng cho việc phát triển ứng dụng di động.

Đọc bài viết này để hiểu thêm về:

  • Tổng quan mối quan hệ Dart Flutter
  • Bắt đầu với Dart trong Flutter
  • Kiến thức cơ bản về Dart cho lập trình viên Flutter
  • Cách Dart hoạt động trong Flutter
  • Các tính nâng cao

Tổng quan về mối quan hệ Dart Flutter

Dart là ngôn ngữ lập trình hướng đối tượng, được phát triển bởi Google, với mục tiêu tạo ra các ứng dụng đa nền tảng có hiệu suất cao. Dart hỗ trợ lập trình bất đồng bộ, biên dịch nhanh và cung cấp nhiều tính năng hiện đại như kiểu dữ liệu tường minh (explicit), mixin, và lập trình hàm (functional programming).

Flutter là framework mã nguồn mở do Google phát triển, cho phép lập trình viên tạo các ứng dụng di động, web và desktop chỉ với một codebase duy nhất. 

Trong hệ sinh thái Flutter, Dart là ngôn ngữ duy nhất được sử dụng để viết mã ứng dụng. Flutter được xây dựng hoàn toàn dựa trên Dart, từ các widget giao diện người dùng cho đến các logic xử lý bên trong. Ngôn ngữ Dart giúp Flutter:

  • Biên dịch mã nguồn thành mã máy gốc (native) để tăng hiệu suất.
  • Hỗ trợ hot reload, cho phép thay đổi giao diện và logic ứng dụng mà không cần khởi động lại.
  • Cung cấp khả năng lập trình bất đồng bộ (async/await) giúp xử lý các tác vụ nền như gọi API hoặc đọc/ghi dữ liệu.

Nhờ sự tích hợp chặt chẽ này, Dart giúp các ứng dụng Flutter hoạt động mượt mà, có khả năng mở rộng và bảo trì dễ dàng.

3 bước bắt đầu với Dart trong Flutter 

Đầu tiên, lập trình viên Flutter cần có kiến thức cơ bản về Dart. Bạn có thể tìm hiểu thêm về ngôn ngữ lập trình này tại bài viết: Dart là gì? Cú pháp, Đặc điểm, Ứng dụng thực tế của Dart 

Sau đó, hãy đọc hướng dẫn dưới đây để bắt đầu với Dart trong Flutter, từ việc cài đặt môi trường đến viết chương trình đơn giản đầu tiên.

Cài đặt Flutter

  1. Truy cập trang web chính thức của Flutter.
  2. Tải xuống phiên bản phù hợp với hệ điều hành của bạn (Windows, macOS, hoặc Linux).
  3. Giải nén tệp và thêm đường dẫn thư mục flutter/bin vào biến môi trường PATH.
  4. Mở terminal và chạy lệnh sau để kiểm tra môi trường đã được cấu hình đầy đủ:
Flutter Doctor

Nếu có thành phần nào còn thiếu, công cụ sẽ hướng dẫn bạn cài đặt.

Tạo dự án Flutter mới

flutter  create my_flutter_app

Lệnh này sẽ tự động tạo ra một cấu trúc dự án với các tệp và thư mục cần thiết.

Một dự án Flutter cơ bản có cấu trúc thư mục như sau:

  • lib/: Chứa mã nguồn chính của ứng dụng (thường là tệp main.dart).
  • android/: Mã nguồn dành cho nền tảng Android.
  • ios/: Mã nguồn dành cho nền tảng iOS.
  • test/: Chứa các bài kiểm thử đơn vị (unit test).
  • pubspec.yaml: Tệp cấu hình các thư viện và tài nguyên.
  • README.md: Mô tả thông tin dự án.

Viết chương trình “Hello, Flutter” với Dart

Bây giờ, hãy thử viết một ứng dụng đơn giản hiển thị dòng chữ “Hello, Flutter”.

Mở tệp lib/main.dart và viết đoạn mã sau:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Hello, Flutter'),
        ),
        body: Center(
          child: Text('Hello, Flutter', style: TextStyle(fontSize: 24)),
        ),
      ),
    );
  }

Chạy ứng dụng bằng lệnh sau trong terminal:

flutter run 

Nếu cấu hình môi trường chính xác, bạn sẽ thấy dòng chữ “Hello, Flutter” hiển thị trên giao diện ứng dụng.

Các tính năng cơ bản của Dart trong Flutter

Xây dựng giao diện người dùng (UI) bằng Dart

Dart là ngôn ngữ chính trong việc xây dựng giao diện người dùng trong Flutter. Các widget trong Flutter được viết bằng Dart để tạo ra các thành phần giao diện linh hoạt và có thể tái sử dụng.

Ví dụ:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Welcome to Flutter)),
        body: Center(child: Text('Hello World')),
      ),
    );
  }
}

Dưới đây là kết quả sau khi chạy đoạn code trên ở cả hai nền tảng thông dụng là iOS và Android:

dart flutter - itviec blog

 

Quản lý trạng thái trong Flutter với Dart

Flutter cung cấp nhiều cách quản lý trạng thái như StatefulWidget, Provider, và Riverpod. Việc quản lý State – các trạng thái trong Flutter là vô cùng quan trọng, quyết định đến logic và cách hoạt động của các thành phần giao diện trong ứng dụng.

Ví dụ:

class Counter extends StatefulWidget {
  @override
  _CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int _count = 0;

  void _increment() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Count: $_count'),
        ElevatedButton(onPressed: _increment, child: Text('Increment')),
      ],
    );
  }
}

Giải thích:

  • Trạng thái count khi vừa khởi tạo có giá trị bằng 0.
  • Khi người dùng tương tác với nút triển khai logic (increment), giá trị biến _count cộng thêm 1.
  • Giao diện của chương trình lúc này được cập nhật và hiển thị giá trị của biến _count này lên màn hình ứng với trạng thái hiện tại của biến _count

Xử lý sự kiện và tương tác người dùng

Dart hỗ trợ các widget tương tác như GestureDetector, ElevatedButton, giúp người dùng thực hiện các thao tác như nhấn nút hoặc kéo thả.

Ví dụ xử lý sự kiện nhấn nút:

ElevatedButton(
  onPressed: () {
    print('Button clicked');
  },
  child: Text('Click Me'),
)

Hàm onPressed được gọi khi người dùng nhấn nút, giúp ứng dụng phản hồi tương tác.

Sử dụng thư viện và plugin Dart trong Flutter

Flutter hỗ trợ nhiều thư viện và plugin được viết bằng Dart để mở rộng tính năng như truy cập API, lưu trữ dữ liệu hoặc tích hợp dịch vụ bên ngoài.

Ví dụ sử dụng thư viện HTTP:

import 'package:http/http.dart' as http;

void fetchData() async {
  var url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');
  var response = await http.get(url);
  if (response.statusCode == 200) {
    print(response.body);
  } else {
    print('Failed to load data');
  }
}

Thư viện HTTP giúp gửi yêu cầu HTTP và xử lý phản hồi từ server.

Dart đóng vai trò trung tâm trong việc xây dựng ứng dụng Flutter bằng cách cung cấp công cụ lập trình mạnh mẽ và linh hoạt, hỗ trợ xây dựng giao diện, quản lý trạng thái, xử lý sự kiện và tích hợp các dịch vụ bên ngoài.

Các tính năng nâng cao của Dart trong Flutter 

Kế thừa và mixin trong Dart

Dart hỗ trợ lập trình hướng đối tượng (OOP) với tính năng kế thừa, cho phép các lớp con kế thừa các thuộc tính và phương thức từ lớp cha.

Ví dụ:

class Animal {
  void makeSound() {
    print('Some sound');
  }
}

class Dog extends Animal {
  @override
  void makeSound() {
    print('Bark');
  }
}

void main() {
  Dog dog = Dog();
  dog.makeSound(); // In ra 'Bark'
}

Giải thích:

  • Lớp Animal định nghĩa một phương thức makeSound().
  • Lớp Dog kế thừa từ Animal và ghi đè phương thức makeSound() để cung cấp âm thanh riêng.
  • Từ khóa @override cho biết phương thức này ghi đè phương thức từ lớp cha.

Mixin cho phép tái sử dụng mã nguồn bằng cách kết hợp nhiều lớp vào một lớp đơn lẻ.

mixin Flyable {
  void fly() => print('Flying');
}

class Bird with Flyable {}

void main() {
  Bird bird = Bird();
  bird.fly(); // In ra 'Flying'
}

Giải thích:

  • mixin là một loại lớp đặc biệt cho phép tái sử dụng các phương thức trong nhiều lớp.
  • Lớp Bird sử dụng từ khóa with để kết hợp mixin Flyable, giúp lớp này có thể gọi phương thức fly().

Extension methods và Generics

Extension methods cho phép mở rộng các lớp hiện có mà không cần kế thừa.

Ví dụ:

extension StringExtension on String {
  String get reversed => split('').reversed.join('');
}

void main() {
  print('hello'.reversed); // In ra 'olleh'
}

Giải thích:

  • extension khai báo một extension method trên lớp String.
  • Thuộc tính reversed chuyển đổi chuỗi thành danh sách ký tự, đảo ngược danh sách và nối lại thành chuỗi mới.

Generics giúp viết các lớp và hàm có thể làm việc với nhiều kiểu dữ liệu.

Ví dụ:

class Box<T> {
  T value;
  Box(this.value);
}

void main() {
  Box<int> intBox = Box(123);
  Box<String> stringBox = Box('Hello');
  print(intBox.value);
  print(stringBox.value);
}

Giải thích:

  • T là một placeholder cho kiểu dữ liệu được chỉ định khi khởi tạo lớp.
  • Box<int> chỉ định lớp Box chứa các giá trị kiểu int, trong khi Box<String> chứa giá trị kiểu String.

Null safety

Null safety trong Dart giúp ngăn ngừa các lỗi null runtime bằng cách xác định rõ ràng biến nào có thể null và biến nào không.

Ví dụ:

String? nullableString;
String nonNullableString = 'Hello';

void main() {
  print(nullableString?.length); // Không gây lỗi
  print(nonNullableString.length); // In ra 5
}

Giải thích:

  • String? chỉ ra rằng biến nullableString có thể nhận giá trị null.
  • Toán tử ?. giúp kiểm tra null trước khi truy cập thuộc tính.
  • nonNullableString không thể null và luôn có giá trị.

Cách tối ưu:

  • Luôn khai báo các biến không nullable nếu có thể.
  • Sử dụng toán tử ??? để xử lý giá trị null.
  • Kiểm tra null trước khi sử dụng các giá trị có thể null.

Cải thiện hiệu suất và tối ưu hóa mã Dart trong Flutter

Cải thiện hiệu suất trong Dart và Flutter có thể đạt được bằng cách:

  • Sử dụng const cho các widget tĩnh.
  • Giảm số lượng widget con trong cây widget.
  • Tối ưu hóa việc sử dụng bộ nhớ bằng cách sử dụng các collection như List, Map, và Set một cách hiệu quả.
  • Sử dụng lazy loading để tải dữ liệu chỉ khi cần thiết.

Ví dụ tối ưu hóa với const:

const Text('Hello, World');

Giải thích:

  • const tạo widget chỉ một lần và tái sử dụng trong toàn bộ ứng dụng.

Cải thiện hiệu suất ứng dụng

  • Sử dụng Isolate để chạy các tác vụ tính toán nặng ở luồng khác.
  • Tối ưu hóa bộ nhớ bằng cách sử dụng các thư viện hiệu quả như cached_network_image để cache hình ảnh.
  • Sử dụng flutter_devtools để phân tích và cải thiện hiệu suất ứng dụng.

Những tính năng nâng cao này giúp các lập trình viên viết mã Dart hiệu quả hơn và tối ưu hóa các ứng dụng Flutter để đạt được hiệu suất cao nhất.

Các câu hỏi thường gặp về Dart Flutter

Dart có phải là ngôn ngữ bắt buộc khi phát triển ứng dụng Flutter không?

Đúng. Dart là ngôn ngữ lập trình chính thức và bắt buộc khi phát triển ứng dụng Flutter. Flutter SDK được xây dựng trên nền tảng Dart và cung cấp các thư viện, API hỗ trợ trực tiếp bằng ngôn ngữ này..

Sự khác biệt giữa Future và Stream trong Dart là gì?

  • Future: Đại diện cho một kết quả bất đồng bộ chỉ xảy ra một lần, ví dụ như kết quả trả về của một API.
  • Stream: Đại diện cho một chuỗi các sự kiện bất đồng bộ, có thể phát sinh nhiều kết quả trong suốt thời gian thực thi, ví dụ như dữ liệu cảm biến hoặc kết quả socket.

Làm thế nào để cải thiện hiệu suất trong ứng dụng Flutter sử dụng Dart?

Một số cách tối ưu hóa bao gồm:

  • Sử dụng từ khóa const cho các widget tĩnh.
  • Giảm số lượng widget con trong cây widget.
  • Tối ưu hóa bộ nhớ với các cấu trúc dữ liệu như List, Map.
  • Dùng thư viện cache như cached_network_image.

Tổng kết 

Dart đóng vai trò quan trọng trong việc phát triển ứng dụng Flutter, cung cấp một nền tảng lập trình mạnh mẽ, linh hoạt và hiệu quả. Từ các kiến thức cơ bản như biến, kiểu dữ liệu, cấu trúc điều khiển, đến các tính năng nâng cao như kế thừa, mixin, và lập trình bất đồng bộ, Dart giúp lập trình viên xây dựng các ứng dụng di động hiệu suất cao và an toàn.

Bằng cách nắm vững các khái niệm và thực tiễn tốt trong Dart, bạn có thể tối ưu hóa hiệu suất ứng dụng, cải thiện trải nghiệm người dùng và giảm thiểu các lỗi trong quá trình phát triển. Việc kết hợp giữa Flutter và Dart mang lại một hệ sinh thái phát triển ứng dụng hiện đại, đơn giản và mạnh mẽ, giúp lập trình viên dễ dàng xây dựng các ứng dụng đa nền tảng với giao diện đẹp và hiệu suất cao.

Hy vọng bài viết này giúp bạn có cái nhìn tổng quan và sâu sắc hơn về vai trò của Dart trong Flutter, cũng như các kỹ thuật và mẹo lập trình giúp tối ưu hóa ứng dụng.