Route — nó là gì, các loại và tạo route trong Flutter

Tác giả: IT Sectr Đã đăng: 2026-07-02 Thời gian đọc: 8 phút

Route là một lớp trừu tượng trong Flutter đại diện cho một màn hình hoặc trang riêng biệt trong lịch sử điều hướng của Navigator. Các triển khai cụ thể của Route — MaterialPageRoute, CupertinoPageRoute và PlatformRoute — xác định cách màn hình được hiển thị và hoạt ảnh nào được sử dụng trong quá trình chuyển đổi. Không giống như widget thông thường, Route có vòng đời riêng với các phương thức didPush, didPop, didReplace và didChangeNext. Theo Flutter API Reference (2026), mỗi Route quản lý ModalBarrier, tính đến các đặc điểm nền tảng cụ thể (vuốt lui trên iOS) và đảm bảo sự cô lập trạng thái giữa các màn hình.

Những điểm chính

  • Route — một lớp màn hình trừu tượng trong Flutter với vòng đời riêng (didPush, didPop, didReplace, didChangeNext)
  • MaterialPageRoute — triển khai Route tiêu chuẩn với hoạt ảnh Material (trượt từ dưới lên) cho Android và máy tính để bàn
  • CupertinoPageRoute — triển khai Route với hoạt ảnh iOS (trượt từ phải + cử chỉ vuốt lui) cho iPhone và iPad
  • Vòng đời — Route trải qua các giai đoạn: Chuyển tiếp, Hoạt động, Không hoạt động và Bị hủy
  • Truyền dữ liệu — Route nhận đối số qua hàm tạo và trả về kết quả qua Future khi hoàn thành

Route trong Flutter là gì

Route là nền tảng của hệ thống điều hướng Flutter. Mỗi màn hình mà người dùng thấy trong ứng dụng được đại diện bởi một đối tượng Route nằm trong ngăn xếp Navigator. Route trừu tượng hóa màn hình khỏi mã điều khiển: Navigator thêm và xóa Route, trong khi bên trong Route là giao diện mà người dùng thấy. Kiến trúc này tách biệt trách nhiệm giữa điều hướng và hiển thị.

Không giống như việc thay thế widget đơn giản, Route cung cấp các dịch vụ không có sẵn cho widget thông thường: ModalBarrier (làm mờ nền khi hộp thoại mở), kiểm soát hoạt ảnh vào và ra, xử lý nút quay lại phần cứng trên Android và tích hợp với hoạt ảnh Hero để chuyển đổi mượt mà giữa các màn hình.

Theo Flutter Cookbook (2026), Route là yếu tố chính cho hoạt ảnh Hero: một widget Hero trên Route này tự động tạo hoạt ảnh chuyển đổi đến widget Hero trên Route tiếp theo, tạo hiệu ứng phần tử “ bay”. Điều này có thể thực hiện được chính xác vì Route giữ cả hai màn hình trong Overlay trong suốt quá trình hoạt ảnh.

Route như một khối xây dựng điều hướng

Route là nền tảng cho cả ứng dụng di động đơn giản (qua Navigator 1.0) và các kịch bản phức tạp với liên kết sâu (Navigator 2.0). Trong Navigator 2.0, Route đại diện cho một Page mà RouterDelegate chuyển đổi từ cấu hình route. Do đó, hiểu Route là cần thiết để làm việc với bất kỳ hệ thống điều hướng Flutter nào — bất kể phương pháp hoặc gói đã chọn.

Các loại Route: MaterialPageRoute và CupertinoPageRoute

Flutter cung cấp một số triển khai Route tích hợp sẵn, mỗi loại điều chỉnh hành vi cho một nền tảng cụ thể. Chọn đúng loại Route ảnh hưởng đến trải nghiệm người dùng: hoạt ảnh Material trên Android và hoạt ảnh Cupertino trên iOS tạo cảm giác ứng dụng “ gốc”.

Loại RouteHoạt ảnhNền tảngĐặc điểm
MaterialPageRouteTrượt từ dưới lên trênAndroid, máy tính để bànBóng khi chuyển đổi, xử lý SafeArea tự động
CupertinoPageRouteTrượt từ phải sang tráiiOS, iPadOSCử chỉ vuốt lui, nền trong suốt khi chuyển đổi
PlatformRouteTự động chọnTất cả nền tảngChọn loại dựa trên TargetPlatform
PageRouteBuilderTùy chỉnhTất cả nền tảngKiểm soát hoàn toàn hoạt ảnh qua AnimationController

MaterialPageRoute: tiêu chuẩn cho Android

MaterialPageRoute là triển khai Route được sử dụng nhiều nhất. Nó tạo hoạt ảnh cho màn hình mới đi vào từ dưới lên trên với sự xuất hiện dần dần. Khi thoát, màn hình tạo hoạt ảnh từ trên xuống dưới, trở về vị trí ban đầu. Thanh công cụ (AppBar) và thân màn hình tạo hoạt ảnh riêng biệt, tạo hiệu ứng phân cấp.

CupertinoPageRoute: phong cách điều hướng iOS

CupertinoPageRoute bắt chước UINavigationController từ iOS. Màn hình mới đi vào từ bên phải, che phủ màn hình trước đó. Đặc điểm chính là hỗ trợ cử chỉ vuốt lui tương tác, được triển khai qua CupertinoBackGestureDetector. Cử chỉ này được xử lý ngay cả giữa hoạt ảnh, cung cấp hành vi tự nhiên quen thuộc với người dùng iPhone.

Vòng đời của Route: từ tạo đến hủy

Route có vòng đời riêng, khác với vòng đời của StatefulWidget thông thường. Hiểu chu kỳ này là cần thiết để khởi tạo dữ liệu đúng cách, đăng ký luồng và giải phóng tài nguyên khi đóng màn hình.

Các giai đoạn vòng đời của Route

Vòng đời của Route bao gồm bốn giai đoạn chính. Chuyển tiếp — Route được tạo và tạo hoạt ảnh khi vào (didPush được gọi). Hoạt động — Route được hiển thị đầy đủ và tương tác với người dùng. Không hoạt động — Route khác che màn hình hiện tại (hộp thoại, trang tính dưới), nhưng Route vẫn ở trong ngăn xếp. Bị hủy — Route bị xóa khỏi ngăn xếp và bị hủy, didPop và dispose được gọi.

Các phương thức vòng đời của Route có thể được ghi đè trong triển khai tùy chỉnh. Ví dụ: didPop được gọi khi Route bị xóa khỏi ngăn xếp — tại đây bạn có thể lưu dữ liệu nháp. didChangeNext được gọi khi Route tiếp theo trong ngăn xếp thay đổi — hữu ích để cập nhật UI khi lịch sử điều hướng thay đổi.

Theo Flutter API Route.didPop (2026), điều quan trọng là không nhầm lẫn vòng đời của Route với vòng đời của State bên trong Route. StatefulWidget bên trong Route có initState và dispose riêng, được gọi trong các giai đoạn Chuyển tiếp và Bị hủy tương ứng. Route sống lâu hơn State bên trong — Route vẫn ở trong Overlay ngay cả khi các widget của nó tạm thời bị ẩn bởi Route khác.

Truyền dữ liệu qua Route giữa các màn hình

Route cung cấp cơ chế truyền dữ liệu cả khi nhập (khi tạo) và khi xuất (khi hoàn thành). Truyền dữ liệu đúng cách qua Route loại bỏ nhu cầu về biến toàn cục và InheritedWidget, làm cho điều hướng an toàn kiểu và có thể dự đoán được.

Để truyền dữ liệu đến màn hình mới, hãy sử dụng hàm tạo của widget nhận hoặc tham số arguments trong Navigator.pushNamed. Bên trong Route, dữ liệu có thể truy cập qua RouteSettings.arguments, được lưu trữ trong đối tượng Route. Cách tiếp cận này hoạt động cho tất cả các loại Route — MaterialPageRoute, CupertinoPageRoute và triển khai tùy chỉnh.

Để trả về dữ liệu, hãy sử dụng đối số thứ hai của Navigator.pop(context, result). Navigator.push trả về Future, hoàn thành với giá trị được truyền vào pop. Nếu pop được gọi mà không có đối số, Future hoàn thành với null. Cơ chế này tương tự như startActivityForResult trong Android và trình xử lý hoàn thành trong iOS, nhưng được triển khai qua Dart Futures.

Truyền dữ liệu qua hàm tạo Route

Khi gọi trực tiếp Navigator.push với MaterialPageRoute, dữ liệu được truyền qua hàm tạo của màn hình đích. MethodChannel không được sử dụng — đây là tương tác Dart thuần túy. Cách tiếp cận này được ưu tiên để truyền an toàn kiểu các đối tượng phức tạp.

Ví dụ tạo Route tùy chỉnh

Hãy xem xét một ví dụ về tạo Route tùy chỉnh với hoạt ảnh và truyền dữ liệu riêng. PageRouteBuilder cho phép định nghĩa hoạt ảnh vào và ra với kiểm soát hoàn toàn về đường cong hoạt ảnh và thời lượng.

dart
// Route tùy chỉnh với hoạt ảnh trượt
Navigator.push(context, PageRouteBuilder(
  pageBuilder: (context, animation, secondaryAnimation) {
    return DetailPage(productId: '42');
  },
  transitionsBuilder: (context, animation, secondaryAnimation, child) {
    const begin = Offset(0.0, 0.3);
    const end = Offset.zero;
    final tween = Tween(begin: begin, end: end);
    final offsetAnimation = animation.drive(tween);
    return SlideTransition(position: offsetAnimation, child: child);
  },
  transitionDuration: const Duration(milliseconds: 400),
));

// Trả về dữ liệu từ màn hình
ElevatedButton(
  onPressed: () => Navigator.of(context).pop({'selected': true, 'id': '42'}),
  child: const Text('Chọn'),
);

// Nhận kết quả trên màn hình gọi
final result = await Navigator.push(context, MaterialPageRoute(
  builder: (context) => const SelectionPage(),
));
if (result != null) {
  print('Đã chọn: ${result['selected']}');
}

Trong ví dụ, PageRouteBuilder định nghĩa hoạt ảnh trượt từ dưới lên tùy chỉnh với độ trong suốt. transitionDuration đặt tốc độ hoạt ảnh. Mã cũng minh họa truyền kết quả: màn hình chi tiết trả về Map với lựa chọn của người dùng và màn hình gọi nhận dữ liệu này qua Future từ push. Route đảm bảo sự cô lập hoàn toàn: các bản nháp trên màn hình chi tiết không ảnh hưởng đến trạng thái danh sách.

Các câu hỏi thường gặp

Sự khác biệt giữa Route và Widget trong Flutter là gì?

Route là một đối tượng quản lý màn hình ở cấp độ điều hướng: nó lưu trữ hoạt ảnh, ModalBarrier và vòng đời. Widget là mô tả của một phần giao diện. Route chứa Widget bên trong nó, nhưng cũng cung cấp các dịch vụ (lớp Overlay, hoạt ảnh Hero) không có sẵn cho widget thông thường. Một Route có thể chứa một hệ thống phân cấp phức tạp các widget với bất kỳ độ sâu nào.

Làm thế nào để tạo Route với hoạt ảnh tùy chỉnh?

Sử dụng PageRouteBuilder với các tham số pageBuilder (xây dựng màn hình) và transitionsBuilder (định nghĩa hoạt ảnh). Trong transitionsBuilder, có sẵn animation (0.0–1.0) và secondaryAnimation cho các hoạt ảnh song song. Để kiểm soát hoàn toàn, hãy tạo một lớp con của Route và ghi đè buildPage, createAnimationController và buildTransitions, cung cấp quyền truy cập vào AnimationController cấp thấp.

Làm thế nào để truyền một đối tượng phức tạp giữa các Route?

Để truyền đối tượng phức tạp, hãy sử dụng hàm tạo của màn hình đích khi gọi trực tiếp Navigator.push hoặc tham số arguments với pushNamed. Đảm bảo đối tượng có thể tuần tự hóa (Map, JSON hoặc lớp tùy chỉnh). Để truyền an toàn kiểu trong Flutter, hãy sử dụng mô hình freezed hoặc json_serializable, đảm bảo giải tuần tự hóa chính xác khi truyền qua RouteSettings.

Tại sao Route có thể không gọi dispose?

Route.dispose không được gọi nếu Route vẫn ở trong ngăn xếp Navigator. Ví dụ: khi mở Route mới, Route cũ chuyển sang trạng thái không hoạt động nhưng không bị hủy — nó vẫn ở trong ngăn xếp để quay lại nhanh. Dispose chỉ được gọi khi Route bị xóa khỏi ngăn xếp qua pop, pushReplacement hoặc pushAndRemoveUntil. Để giải phóng tài nguyên, hãy sử dụng dispose của State bên trong Route, không phải dispose của chính Route.

Làm thế nào để kiểm tra Route nào đang hoạt động?

Sử dụng ModalRoute.of(context) để lấy Route hiện tại từ BuildContext. Thuộc tính ModalRoute.isActive cho biết Route có phải là màn hình hiện đang hiển thị hay không. ModalRoute.isCurrent — true nếu Route là đỉnh của ngăn xếp. Để quan sát các thay đổi của ngăn xếp, hãy đăng ký các quan sát viên Navigator qua RouteAware và RouteObserver, thông báo về các thay đổi Route hoạt động.

Tóm tắt

  • Route — một lớp màn hình trừu tượng trong Flutter với vòng đời (didPush, didPop, didReplace, didChangeNext) và hỗ trợ ModalBarrier và hoạt ảnh Hero
  • MaterialPageRoute — triển khai Android với hoạt ảnh trượt từ dưới lên, bóng và SafeArea tự động
  • CupertinoPageRoute — triển khai iOS với hoạt ảnh trượt từ phải và cử chỉ vuốt lui tương tác
  • PageRouteBuilder — tiện ích để tạo Route với hoạt ảnh tùy chỉnh qua transitionsBuilder và AnimationController
  • Truyền dữ liệu — qua hàm tạo Route (push) hoặc arguments (pushNamed) khi nhập; qua Navigator.pop(context, result) khi xuất với Future
  • Vòng đời — bốn giai đoạn: Chuyển tiếp (didPush), Hoạt động, Không hoạt động (bị Route khác che), Bị hủy (didPop + dispose)
  • Cô lập màn hình — mỗi Route có BuildContext và trạng thái riêng, ngăn rò rỉ và đơn giản hóa quản lý dữ liệu

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.

Thảo luận dự án

Đọc thêm