Flutter Widgets — các khối xây dựng cơ bản của giao diện người dùng trong framework Google Flutter, được phát hành ở phiên bản ổn định 1.0 vào tháng 12 năm 2018. Trong Flutter, mọi thứ đều là widget: từ màn hình và nút bấm đến khoảng đệm và căn chỉnh. Các widget tạo thành một cây (widget tree) mà Flutter render trên engine Skia/Impeller của riêng nó, bỏ qua các thành phần gốc của nền tảng. Theo Google I/O (2025), Flutter được sử dụng trong hơn 500.000 ứng dụng trên Google Play và App Store. Kiến trúc Flutter chia widget thành StatelessWidget (bất biến) và StatefulWidget (có trạng thái thay đổi được thông qua đối tượng State).
Những Điểm Chính
Flutter Widgets — tất cả các phần tử UI trong framework Flutter, được triển khai dưới dạng các lớp Dart bất biến (immutable). Widget là cấu hình của một phần tử UI: kích thước, màu sắc, vị trí và trình xử lý sự kiện. Không giống như Android (XML + View) hay iOS (Storyboard + UIView), Flutter không sử dụng các thành phần gốc — mọi thứ đều được vẽ bởi engine Skia (Android/iOS/Linux) hoặc Impeller (iOS/macOS) trên Canvas. Điều này đảm bảo giao diện nhất quán trên tất cả các nền tảng mà không có sự khác biệt về nền tảng. Flutter đi kèm với hai bộ widget: Material Widgets (Google Material Design 3 cho Android/web) và Cupertino Widgets (Apple HIG cho iOS/macOS). Nhà phát triển có thể kết hợp cả hai bộ trong một ứng dụng. Mỗi widget có phương thức build() trả về một widget con hoặc sự kết hợp của chúng — đây là cách cây widget được xây dựng.
Flutter hoạt động với ba cây: Widget Tree (cấu hình, được nhà phát triển tạo), Element Tree (ánh xạ widget đến vị trí của nó trong cây, được framework quản lý) và Render Tree (các đối tượng tính toán bố cục và thực hiện vẽ). Một Widget tạo ra một Element, Element tạo ra một RenderObject. Element được tái sử dụng khi cấu hình thay đổi (rebuild) — đây là cơ chế tối ưu hóa của Flutter: nếu loại widget và key khớp nhau, Element không được tạo lại mà được cập nhật với cấu hình mới. Hiểu ba cây là chìa khóa để tối ưu hóa hiệu suất ứng dụng Flutter.
StatelessWidget — widget không lưu trữ trạng thái nội bộ. Nó nhận tham số qua hàm tạo và hiển thị chúng mà không có khả năng thay đổi sau khi build. StatelessWidget lý tưởng cho các phần tử tĩnh: tiêu đề, biểu tượng, hình đại diện, danh sách với dữ liệu cố định. Phương thức build() được gọi một lần khi tạo và khi widget cha thay đổi. Vì StatelessWidget không có trạng thái, nó không yêu cầu đối tượng State riêng — build() được định nghĩa trực tiếp trong lớp widget.
import 'package:flutter/material.dart';
class ProfileHeader extends StatelessWidget {
final String name;
final String avatarUrl;
const ProfileHeader({super.key, required this.name, required this.avatarUrl});
@override
Widget build(BuildContext context) {
return Row(
children: [
CircleAvatar(
radius: 24,
backgroundImage: NetworkImage(avatarUrl),
),
const SizedBox(width: 12),
Text(
name,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
);
}
}ProfileHeader — StatelessWidget nhận name và avatarUrl qua hàm tạo. CircleAvatar hiển thị hình đại diện, Text hiển thị tên. Widget không thể thay đổi các giá trị này sau khi tạo. Sử dụng hàm tạo const (const ProfileHeader) cho phép Flutter tái sử dụng thể hiện widget trong quá trình rebuild của cha — một tối ưu hóa vi mô được khuyến nghị cho tất cả StatelessWidget.
StatefulWidget — widget có trạng thái thay đổi được lưu trong đối tượng State riêng biệt. Bản thân StatefulWidget là bất biến, giống như StatelessWidget. Phần có thể thay đổi được ủy quyền cho State: State là đối tượng được tạo một lần và tồn tại qua nhiều lần rebuild widget. Khi trạng thái thay đổi (setState()), Flutter gọi build() trên State, cập nhật UI. StatefulWidget được sử dụng cho các phần tử tương tác: bộ đếm, trường văn bản, hộp kiểm, hoạt ảnh, bộ hẹn giờ.
import 'package:flutter/material.dart';
class LikeButton extends StatefulWidget {
const LikeButton({super.key});
@override
State<LikeButton> createState() => _LikeButtonState();
}
class _LikeButtonState extends State<LikeButton> {
bool liked = false;
int count = 42;
void _toggleLike() {
setState(() {
liked = !liked;
count += liked ? 1 : -1;
});
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _toggleLike,
child: Text(liked ? '♥ $count' : '♡ $count'),
);
}
}LikeButton — StatefulWidget với lớp State _LikeButtonState. Các trường liked và count là trạng thái được lưu trong State và không bị đặt lại khi rebuild. setState() thông báo cho Flutter rằng UI cần được xây dựng lại. Flutter không tạo lại State ở mỗi lần rebuild của cha — chỉ khi cấu hình thay đổi (key hoặc loại widget). Tại IT Sectr, chúng tôi sử dụng StatelessWidget để hiển thị và StatefulWidget cho các thành phần tương tác, tuân theo nguyên tắc giảm thiểu StatefulWidget đến ranh giới đột biến.
Widget Tree — cấu trúc phân cấp của các widget mô tả UI ứng dụng. Flutter chuyển đổi Widget Tree thành Element Tree: mỗi Widget tạo một Element, theo dõi vị trí của nó trong cây và kết nối với RenderObject. Render Tree thực hiện bố cục (xác định kích thước và vị trí) và vẽ (render). Element là một lớp tối ưu hóa quan trọng: nếu loại widget và key không thay đổi trong quá trình rebuild, Element được tái sử dụng, cập nhật cấu hình mà không tạo lại RenderObject. Điều này đảm bảo hiệu suất của Flutter ở tốc độ khung hình cao (60/120 FPS).
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Widget Flutter')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.flutter_dash, size: 80),
const SizedBox(height: 16),
const Text(
'Xin chào, Flutter!',
style: TextStyle(fontSize: 24),
),
],
),
),
);
}
}Cây widget HomeScreen: Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold là widget bố cục gốc của Material Design. Center căn giữa Column con. Column sắp xếp các con theo chiều dọc với căn giữa (mainAxisAlignment.center). Flutter tính toán bố cục từ trên xuống (các ràng buộc được truyền từ cha) và kích thước từ dưới lên (sizedByParent hoặc sizing từ con).
BuildContext — bộ mô tả vị trí của widget trong Element Tree. Mỗi phương thức build() nhận một BuildContext, qua đó widget có thể truy cập: MediaQuery (kích thước màn hình, hướng, mật độ pixel, vùng an toàn), Theme (MaterialThemeData hoặc CupertinoThemeData), Navigator (ngăn xếp điều hướng), ScaffoldMessenger (SnackBar), InheritedWidget (truyền dữ liệu xuống cây). BuildContext không nên được lưu sau khi build() kết thúc hoặc sử dụng ngoài ngữ cảnh đồng bộ — điều này gây ra lỗi như “Scaffold.of() called with a context that does not contain a Scaffold”. Thay vì lưu context, hãy sử dụng widget Builder hoặc mẫu InheritedWidget để truy cập dữ liệu.
Key — tham số tùy chọn của hàm tạo mỗi widget (super.key). Key giúp Flutter nhận dạng widget khi thứ tự hoặc số lượng phần tử trong danh sách thay đổi. Không có key, Flutter so sánh widget theo loại và vị trí; khi thêm một phần tử vào giữa danh sách mà không có key, Flutter tái sử dụng Element cho sai widget, gây ra lỗi trạng thái (StatefulWidget) và vấn đề hoạt ảnh. Sử dụng ValueKey (định danh duy nhất) cho danh sách, ObjectKey(dựa trên đối tượng dữ liệu), UniqueKey (đảm bảo duy nhất ở mỗi lần rebuild — để tạo lại bắt buộc).
Flutter SDK (phiên bản ổn định 3.3+, Dart 3+) bao gồm hơn 200 widget tích hợp được chia thành các danh mục: Layout (Row, Column, Stack, Container, Expanded, Flexible, Wrap, GridView, ListView, CustomScrollView), Material Design (Scaffold, AppBar, Card, Drawer, BottomNavigationBar, FloatingActionButton, TabBar, Chip, DataTable), Cupertino (CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton, CupertinoTabBar), Painting & Effects (Opacity, DecoratedBox, ClipRect, Transform, BackdropFilter, ShaderMask), Async (FutureBuilder, StreamBuilder) và Accessibility (Semantics, MergeSemantics, ExcludeSemantics). Widget bố cục là nền tảng của mọi UI Flutter: Row cho chuỗi ngang, Column cho dọc, Stack cho các phần tử chồng lên nhau, Container với BoxDecoration để trang trí.
| Danh mục | Widget chính | Mục đích |
|---|---|---|
| Layout | Row, Column, Stack, Container, Expanded, Flexible | Định vị và định cỡ các phần tử con |
| Material | Scaffold, AppBar, Card, Drawer, FAB, TabBar | Thành phần UI Material Design 3 |
| Cupertino | CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton | Thành phần kiểu iOS |
| Painting | Opacity, ClipRect, Transform, DecoratedBox, BackdropFilter | Hiệu ứng hình ảnh và cắt xén |
| Async | FutureBuilder, StreamBuilder | Tải dữ liệu bất đồng bộ với trạng thái UI |
| Accessibility | Semantics, MergeSemantics | Đánh dấu ngữ nghĩa cho trình đọc màn hình |
Câu Hỏi Thường Gặp
StatelessWidget không có trạng thái nội bộ — tất cả dữ liệu được truyền qua hàm tạo và không thay đổi. StatefulWidget lưu trữ trạng thái thay đổi trong đối tượng State riêng biệt tồn tại qua các lần rebuild. Thay đổi trạng thái gọi setState(), và Flutter xây dựng lại UI. Sử dụng StatelessWidget cho các phần tử bất biến; sử dụng StatefulWidget cho các phần tử tương tác.
BuildContext là bộ mô tả vị trí của widget trong Element Tree, được truyền cho phương thức build(). Thông qua context, widget truy cập MediaQuery, Theme, Navigator, ScaffoldMessenger và InheritedWidget. BuildContext không nên được lưu sau khi build() kết thúc. Để truy cập dữ liệu, hãy sử dụng widget Builder hoặc InheritedWidget.
Có, Flutter sử dụng Dart làm ngôn ngữ lập trình duy nhất. Dart là ngôn ngữ kiểu tĩnh với null safety, sound null safety, extension methods và pattern matching. Để bắt đầu, kiến thức Dart cơ bản là đủ: lớp, hàm, async/await, collection. Dart được biên dịch thành mã gốc (AOT) qua Dart Native và thành JavaScript (cho web) qua Dart2JS.
Không, Flutter hỗ trợ sáu nền tảng: iOS, Android, Web, macOS, Windows, Linux. Hơn 90% mã được chia sẻ trên tất cả các nền tảng. Các điều chỉnh nền tảng (máy ảnh, hệ thống tệp) được triển khai qua plugin hoặc kênh nền tảng. Cho máy tính để bàn, Flutter sử dụng trình bao cửa sổ Flutter Desktop; cho web, nó sử dụng engine CanvasKit (WebGL) hoặc trình render HTML.
Flutter đạt được 60/120 FPS nhờ: engine 2D riêng (Skia/Impeller), không có cầu nối gốc (không giống React Native), ba cây (Widget → Element → Render) với tái sử dụng Element khi loại/key không đổi, thuật toán bố cục một chiều (ràng buộc xuống, kích thước lên) và RepaintBoundary để cách ly việc vẽ lại các khu vực riêng lẻ của màn hình.
Tổng Kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm