Ở phần trước, mình đã tìm hiểu cách di chuyển qua lại giữa các Page một cách đơn giản nhất. Phần này mình sẽ tìm hiểu cách gửi và nhận dữ liệu giữa các Page.
1. Gửi Dữ Liệu
-
Auto_Route chỉ hỗ trợ một phương thức là gửi dữ liệu thông qua contructors. Cách thức triển khai như dưới đây :
-
Tại Page mà chúng ta muốn di chuyển đến, mình tạo contructor chứa các filed cần thiết để nhận dữ liệu từ màn hình trước.
-
Khi thực hiện Push Page, mình sẽ truyền các giá muốn gửi thông qua contructor này.
class PageB extends StatefulWidget { // Tạo filed paramter để nhận data. final String paramter; const PageB({super.key, required this.paramter}); @override State<PageB> createState() => _PageBState(); }
ElevatedButton( child: const Text('Next Page B with Push()'), onPressed: () { var autoRouter = AutoRouter.of(context); autoRouter.push(RouteB(paramter: "This is Data from Page A")); }, ),
-
Chúng ta có thể thấy, lúc Push chúng ta khởi tạo
RouteB
chứ không khởi tạo PageB. Nhưng RouteB vẫn có contructors tương ứng. Đó là nhờ tool generate hỗ trợ chúng ta làm điều này.
-
-
Dùng PathParams
-
Như bạn thấy, cách trên buộc mình phải dùng hàm
push
. Nếu muốn dùngpushNamed
thì không thể truyền, vì hàmpushNamed
nó nhận một chuỗi path thay vì mộtRoute
. PathParams sẽ hỗ trợ chúng ta truyền tham số mà vẫn có thể dùng hàmpushNamed
-
Cách làm như sau :
- Tại class AppRouter, trên đối tượng AutoRoute, chỉ định một pathParams với cú pháp sau :
“
/: " ex : “/PageA/:paramters”
-
Tại Page đích, bạn cũng thực hiện khai báo contructor. Khác một chỗ là chúng ta sẽ thêm một annotate vào tham số của contructor.
@RoutePage() class PageC extends StatefulWidget { final String paramters; const PageC({super.key, @PathParam("PathParamKey") required this.paramters}); @override State<PageC> createState() => _PageCState(); }
AutoRoute( path: "${PathRouter.pageC}/:PathParamKey", page: RouteC.page, ),
-
Tại PageB, chúng ta thực hiện gọi hàm
pushNamed
ElevatedButton( child: const Text('Next Page C'), onPressed: () { var combilePath = "${PathRouter.pageC}/This is data from Page B"; var autoRouter = AutoRouter.of(context); autoRouter.pushNamed(combilePath); }, ),
-
-
-
Dùng QueryParams (Khuyên dùng)
-
Khi dùng PathPrams chúng ta cần định nghĩa tham số ở AppRouter. Trường hợp chúng ta muốn truyền vào tham số thì bắt buộc phải định nghĩa. QueryParams giúp cải thiện điều này
-
Tại Page đích, chúng ta thay thế annotate
@PathParam bằng@QueryParam
@RoutePage() class PageD extends StatefulWidget { final String? paramter; const PageD({super.key, @QueryParam("QueryParamKey") required this.paramter}); @override State<PageD> createState() => _PageDState(); }
-
Filed lúc này được yêu cầu là một nullable field, nếu không tool generate sẽ báo lỗi.
-
Nếu bạn đã quen với kiểu query trên web thì nó giống như vậy.
// <PathRoute>?<QueryParam>=<Data> Ex : "RouteB?paramters='This is data from Page B'"
ElevatedButton( child: const Text('Next Page D'), onPressed: () { var autoRouter = AutoRouter.of(context); var combilePath = "${PathRouter.pageD}?QueryParamKey='This is data from C'"; autoRouter.pushNamed(combilePath); }, ),
-
Tips : Bạn có thể access queryParams thông qua Route
var autoRouter = AutoRouter.of(context); autoRouter.current.queryParams;
-
2. Nhận Dữ Liệu
-
Auto_Route thực hiện cơ chế đợi chờ kết quả. Mình sẽ mô tả như sau:
-
Giả sử app đang đứng tại Page A.
-
Gọi hàm push để hiển thị Page B
-
Page B xử lý xong các logic cần thiết.
-
Pop Page B để trở về Page B
-
Page A nhận kết quả rồi xử lý tiếp các logic bên dưới nó.
-
-
Để nhận dữ liệu chúng ta làm theo các bước sau :
-
Ở Page B, Xác định kiểu dữ liệu muốn trả về
@RoutePage<bool>() class PageB extends StatelessWidget{..}
-
Thực hiện lệnh generate ra code
flutter packages pub run build_runner build
-
Khi thực hiện push, chúng ta truyền kiểu dữ vào hàm này.
var result = await router.push<bool>(RouteB);
-
Tại PageB, mình sẽ truyền data trả về thông qua hàm pop
router.pop<bool>(true);
-
-
Với cách trên, chúng ta phải đợi cho đến khi PageB xử lý xong thì mới có thể xử lý các logic khác.
-
Trường hợp chúng ta muốn xử lý ngay thì chúng có thể dùng cách thứ 2, tạo một callBack.
-
Cách này giống như bạn truyền data sang một màn hình hình mới, thay vì chuyển các kiễu dữ liệu cần thiết, bây giờ mình truyền một Function. Tại PageB function nên được gọi trước khi Page B trở về.
-
Cách này có ưu điểm là chúng ta không cần chỉnh định kiểu dữ liệu cho
RouterPage
@RoutePage() class BookDetailsPage extends StatelessWidget { const BookDetailsRoute({this.book, required this.onRateBook}); final Book book; final void Function(int) onRateBook; ...
context.pushRoute( BookDetailsRoute( book: book, onRateBook: (rating) { // handle result }), );
onRateBook(RESULT); context.popRoute();
-
Tổng Kết :
- Phần này mình đã tìm hiểu được cách gửi và nhận dữ liệu trong gói AutoRoute