GetX — một micro-framework nhẹ cho Flutter kết hợp quản lý trạng thái, điều hướng và tiêm phụ thuộc trong một gói. Được phát triển bởi Amir Hossein Abdorashidi, GetX cung cấp boilerplate tối thiểu: không Stream, không ChangeNotifier, không BuildContext cho điều hướng. Theo pub.dev, GetX đã đạt hơn 13 nghìn lượt thích, trở thành một trong những gói Flutter phổ biến nhất.
Những điểm chính
GetX — một micro-framework tất-cả-trong-một cho Flutter giải quyết ba nhiệm vụ phát triển chính: quản lý trạng thái, điều hướng (định tuyến) và tiêm phụ thuộc (DI). GetX không yêu cầu Stream, ChangeNotifier, Builders hay đăng ký — mọi phản ứng được cung cấp bởi các wrapper Rx dựa trên GetValue và GetStream, hoạt động nhanh hơn ChangeNotifier hàng chục lần.
GetX được định vị như một giải pháp thay thế cho tổ hợp Provider + Navigator + get_it/kiwi. Thay vì cài đặt ba gói khác nhau và viết 10 dòng cấu hình, GetX cung cấp mọi thứ sẵn sàng với một dòng duy nhất: GetMaterialApp thay vì MaterialApp. Điều hướng hoạt động qua Get.to(NextScreen()) mà không cần BuildContext, và DI qua Get.put(Service()) mà không cần cây Provider.
Theo Khảo sát Cộng đồng Flutter 2025, GetX được sử dụng trong 43% dự án Flutter. Lý do chính để chọn nó: ngưỡng đầu vào tối thiểu (5 phút để học), không boilerplate (mã giảm 60-70% so với Provider hay BLoC) và phát triển MVP nhanh. Các nhà phê bình chỉ ra vi phạm nguyên tắc phân tách mối quan tâm và độ phức tạp khi gỡ lỗi.
Obx — một widget GetX phản ứng tự xây dựng lại khi các biến Rx thay đổi. Obx không yêu cầu đăng ký, dispose hay hàm Builder — chỉ cần bọc widget trong Obx và sử dụng biến Rx bên trong. Obx tự động theo dõi biến Rx nào được sử dụng và chỉ vẽ lại khi chúng thay đổi.
class CounterController extends GetxController {
final count = 0.obs;
void increment() => count++;
}
class CounterScreen extends StatelessWidget {
final controller = Get.put(CounterController());
@override
Widget build(context) => Obx(() => Text('${controller.count}'));
}Biến Rx: .obs — một getter bọc bất kỳ giá trị nào thành đối tượng Rx. GetX cung cấp các lớp Rx được định kiểu: RxInt, RxString, RxDouble, RxBool, RxList, RxMap. Tất cả biến Rx hoạt động như các kiểu nguyên thủy thông thường: count++, name.value = 'Hello', items.add(item). Thay đổi tự động thông báo cho người đăng ký Obx.
GetBuilder — một giải pháp thay thế cho Obx không cần Rx, hoạt động qua lệnh gọi update() thủ công. GetBuilder.filter — để cập nhật có mục tiêu theo khóa ID. Obx nhanh hơn (theo dõi phụ thuộc tự động), GetBuilder dễ dự đoán hơn (gọi cập nhật rõ ràng). Obx được khuyến nghị cho các tình huống đơn giản và GetBuilder cho các widget phức tạp với nhiều phụ thuộc.
GetxController — một lớp cơ sở cho logic nghiệp vụ với hỗ trợ vòng đời. GetxController có các phương thức: onInit() (khởi tạo), onReady() (sau khung hình đầu tiên), onClose() (dọn dẹp tài nguyên). Không giống ChangeNotifier và StateNotifier, GetxController tự động quản lý đăng ký: khi trang bị hủy, tất cả biến Rx và Workers đều bị hủy đăng ký.
class AuthController extends GetxController {
final user = Rx<User?>(null);
final isLoading = false.obs;
@override
void onInit() {
ever(isLoading, (_) => print('Loading: $isLoading'));
super.onInit();
}
Future<void> login(String email, String password) async {
isLoading.value = true;
user.value = await api.login(email, password);
isLoading.value = false;
}
}Workers — các tiện ích phản ứng của GetX: ever (được gọi ở mọi thay đổi), once (chỉ ở thay đổi đầu tiên), debounce (có độ trễ), interval (không quá N lần mỗi giây). Workers giải quyết các tác vụ điển hình: xác thực trường (debounce), phân tích (once), đồng bộ hóa (ever). Workers tự động hủy đăng ký khi onClose() được gọi, ngăn chặn rò rỉ bộ nhớ.
Điều hướng GetX không yêu cầu BuildContext để chuyển đổi giữa các màn hình. Thay vì Navigator.push(context, MaterialPageRoute(...)), sử dụng Get.to(NextScreen()) — có thể gọi từ bất kỳ đâu, bao gồm Controller không có quyền truy cập BuildContext. GetX hỗ trợ route có tên, hoạt ảnh, middleware và truyền đối số không cần MaterialPageRoute.
// Điều hướng thông thường
Get.to(ProfileScreen());
Get.back();
Get.off(LoginScreen()); // thay thế route hiện tại
Get.offAll(HomeScreen()); // xóa ngăn xếp
// Route có tên
Get.toNamed('/profile', arguments: 'user123');
Get.offNamed('/login');
// Middleware
GetPage(
name: '/profile',
page: () => ProfileScreen(),
middlewares: [AuthMiddleware()],
)GetPage và GetPages: GetX sử dụng GetPages thay vì routes trong MaterialApp. Middleware — kiểm tra xác thực, chuyển hướng, phân tích trước khi vào màn hình. Transition — hoạt ảnh chuyển tiếp tích hợp: fadeIn, zoom, leftToRight, topToBottom. Bindings — một lớp khởi tạo Controller và phụ thuộc khi vào một route. Bindings giải quyết vấn đề khởi tạo lười biếng: Controller chỉ được tạo khi màn hình được mở.
Get.put — đăng ký một thể hiện trong container DI. Get.find — lấy một thể hiện từ container. Get.lazyPut — khởi tạo lười biếng (được tạo ở lần gọi find đầu tiên). Get.putAsync — khởi tạo bất đồng bộ (cho dịch vụ có init). Get.delete — xóa khỏi container (được Bindings tự động gọi khi route bị hủy).
| Phương thức | Khi nào được tạo | Khi nào bị xóa |
|---|---|---|
| Get.put | Ngay lập tức | Get.delete hoặc onClose |
| Get.lazyPut | Ở lần find đầu tiên | Get.delete hoặc onClose |
| Get.putAsync | Sau khi Future hoàn thành | Get.delete hoặc onClose |
| Get.create | Ở mỗi lần find (factory mới) | Không |
DI của GetX — container DI đơn giản nhất trong Flutter. Không cây Provider, không Module, không Scope. Get.put(Repository()) trong Controller hoặc main.dart làm cho đối tượng có thể truy cập ở mọi nơi trong ứng dụng qua Get.find<Repository>(). DI của GetX cũng hỗ trợ gắn thẻ (tag: 'api') và tính bền vững (permanent: true) để ngăn xóa.
Hiệu suất GetX dựa trên các wrapper Rx hoạt động qua GetStream — một triển khai Stream tùy chỉnh được tối ưu hóa cho Flutter. Theo điểm chuẩn của GetX, biến Rx nhanh hơn 2-3 lần so với ChangeNotifier và nhanh hơn 5-7 lần so với BLoC khi cập nhật thường xuyên (30+ fps). GetX không sử dụng BuildContext cho đăng ký, loại bỏ việc xây dựng lại cây widget trong quá trình điều hướng.
Thực hành tốt nhất: sử dụng GetBuilder thay vì Obx cho các widget có nhiều phần tử con (danh sách, bảng). Chia Controller theo mô-đun chức năng thay vì một Controller khổng lồ cho mỗi trang. Sử dụng Bindings để khởi tạo Controller, không phải Get.put trong phương thức build. GetView — StatelessWidget rút gọn với truy cập Controller qua controller không cần Get.find.
Hạn chế đã biết: GetX sử dụng biến toàn cục (Get.find, Get.to), có thể gây khó khăn cho việc kiểm thử. Giả lập phụ thuộc qua GetX yêu cầu Get.replace() hoặc Get.reset() giữa các bài kiểm thử. Để cô lập, Get.testMode = true được khuyến nghị. GetX không được khuyến nghị cho các ứng dụng yêu cầu kiến trúc chặt chẽ với ranh giới lớp rõ ràng — trong trường hợp này, BLoC hoặc Riverpod với tạo mã là lựa chọn tốt hơn.
Câu hỏi thường gặp
GetX — một micro-framework với DI, điều hướng và phản ứng Rx riêng. Provider — chỉ quản lý trạng thái qua ChangeNotifier và InheritedWidget. GetX không yêu cầu BuildContext, có điều hướng và DI tích hợp, giảm boilerplate 60-70%. Provider sử dụng Navigator tiêu chuẩn của Flutter và yêu cầu giải pháp của bên thứ ba cho DI. GetX nhanh hơn trong phát triển, Provider gần với API Flutter gốc hơn.
Workers — các tiện ích để xử lý phản ứng các thay đổi của biến Rx. ever — callback ở mọi thay đổi, once — chỉ ở thay đổi đầu tiên, debounce — có độ trễ (cho trường tìm kiếm), interval — không quá N lần (cho phân tích). Workers được khai báo trong onInit() của GetxController và tự động hủy đăng ký trong onClose(). Điều này thay thế addListener/removeListener thủ công với ChangeNotifier.
GetX cung cấp Get.testMode = true để bật chế độ kiểm thử. Các phụ thuộc được thay thế qua Get.replace<Service>(mockService). Giữa các bài kiểm thử, Get.reset() được gọi để dọn sạch container DI. Controller được kiểm thử trực tiếp không cần Flutter: final c = CounterController(); c.increment(); expect(c.count.value, 1). Cho widget có Obx, sử dụng tester.pumpWidget với InjectMocker.
GetX phù hợp cho dự án ở mọi quy mô nhưng yêu cầu kỷ luật. Cho dự án lớn (10+ màn hình), sử dụng: Bindings để cô lập Controller, mô-đun (tệp GetPages cho mỗi tính năng), GetView thay vì Get.find thủ công trong build. Rủi ro chính là lạm dụng truy cập toàn cục (Get.find ở bất kỳ đâu). Đánh giá mã nghiêm ngặt và hướng dẫn kiến trúc giải quyết vấn đề này. Nhiều ứng dụng sản xuất với hàng triệu người dùng chạy trên GetX.
Bindings — một lớp kết nối route với các phụ thuộc của nó. Khi vào một màn hình, Binding tạo Controller và dịch vụ qua Get.lazyPut, và xóa chúng khi thoát. Bindings triển khai khởi tạo lười biếng: Controller không tồn tại trong bộ nhớ cho đến khi màn hình được mở. Điều này tiết kiệm RAM và thời gian khởi động ứng dụng. Được khai báo trong GetPage: GetPage(name: '/profile', page: () => ProfileScreen(), binding: ProfileBinding()).
Tóm tắ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