Jonny Borges

fix navigate to same route

@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 16
17 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png) 17 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png)
18 18
19 -- [Về Getx](#về-getx) 19 +- [Về GetX](#về-getx)
20 - [Cài Đặt](#cài-đặt) 20 - [Cài Đặt](#cài-đặt)
21 - [Counter App với GetX](#counter-app-với-getx) 21 - [Counter App với GetX](#counter-app-với-getx)
22 - [Tam Trụ](#tam-trụ) 22 - [Tam Trụ](#tam-trụ)
@@ -37,7 +37,7 @@ @@ -37,7 +37,7 @@
37 - [Đổi Theme](#đổi-theme) 37 - [Đổi Theme](#đổi-theme)
38 - [GetConnect](#getconnect) 38 - [GetConnect](#getconnect)
39 - [Cấu hình mặc định](#cấu-hình-mặc-định) 39 - [Cấu hình mặc định](#cấu-hình-mặc-định)
40 - - [Tùy chỉnh](#tùy-chỉnh) 40 + - [Cấu hình tùy chỉnh](#cấu-hình-tùy-chỉnh)
41 - [GetPage Middleware](#getpage-middleware) 41 - [GetPage Middleware](#getpage-middleware)
42 - [Ưu tiên](#ưu-tiên) 42 - [Ưu tiên](#ưu-tiên)
43 - [Chuyển hướng](#chuyển-hướng) 43 - [Chuyển hướng](#chuyển-hướng)
@@ -64,7 +64,7 @@ @@ -64,7 +64,7 @@
64 - [Cách cống hiến](#cách-cống-hiến) 64 - [Cách cống hiến](#cách-cống-hiến)
65 - [Các bài báo và video](#các-bài-báo-và-video) 65 - [Các bài báo và video](#các-bài-báo-và-video)
66 66
67 -# Về Getx 67 +# Về GetX
68 68
69 - GetX hướng tới sự nhỏ gọn và giải pháp tối ưu cho Flutter với tốc độ ưu việt trong quản lý state, nạp dependency thông minh, và quản lý route nhanh chóng và thực tế. 69 - GetX hướng tới sự nhỏ gọn và giải pháp tối ưu cho Flutter với tốc độ ưu việt trong quản lý state, nạp dependency thông minh, và quản lý route nhanh chóng và thực tế.
70 70
@@ -74,29 +74,29 @@ @@ -74,29 +74,29 @@
74 74
75 - **NĂNG SUẤT:** GetX sử dụng một cú pháp dễ dàng và dễ thở. Bất kể bạn muốn làm gì, luôn có một cách dễ dàng hơn với GetX. Nó sẽ tiết kiệm hàng giờ phát triển và sẽ cung cấp hiệu suất tối đa mà ứng dụng của bạn có thể mang lại. 75 - **NĂNG SUẤT:** GetX sử dụng một cú pháp dễ dàng và dễ thở. Bất kể bạn muốn làm gì, luôn có một cách dễ dàng hơn với GetX. Nó sẽ tiết kiệm hàng giờ phát triển và sẽ cung cấp hiệu suất tối đa mà ứng dụng của bạn có thể mang lại.
76 76
77 - Nói chung, nhà phát triển nên quan tâm đến việc xóa controller ra khỏi memory. Với GetX, các tài nguyên sẽ  
78 - TỰ ĐỘNG xóa khỏi memory khi không dùng theo mặc định. Nếu bạn muốn giữ nó trong memory, bạn phải khai báo rõ ràng "permanent: true" trong phần dependency của mình. Từ đó, bạn sẽ tiết kiệm thời gian và ít phụ thuộc vào memory. Theo mặc định, tính năng tải dependency cũng lười biếng. 77 + Nói chung, nhà phát triển nên quan tâm đến việc xóa những controller ra khỏi bộ nhớ. Với GetX, mặc định các tài nguyên sẽ
  78 + TỰ ĐỘNG xóa khỏi bộ nhớ khi không dùng nữa. Nếu bạn muốn giữ nó trong bộ nhớ, bạn phải khai báo rõ ràng "permanent: true" trong phần dependency của mình. Từ đó, bạn sẽ tiết kiệm thời gian và giảm rủi ro khi phụ thuộc vào bộ nhớ. Theo mặc định, tính năng tải dependency cũng lười biếng.
79 79
80 - **TỔ CHỨC:** 80 - **TỔ CHỨC:**
81 - GetX cho phép tách toàn bộ Chế độ xem, presentation logic, business logic, nạp dependencies và điều hướng. Bạn không "context" để điều hướng giữa các route, vì vậy bạn sẽ độc lập trong sơ đồ widget (trực quan hóa). Bạn không cần "context" để truy cập Controller / Blocs của mình thông qua một InheritedWidget, vì vậy bạn hoàn toàn tách rời presentation logic và business logic khỏi lớp trực quan của mình. Bạn không cần phải đưa các Controller / Models / Blocs vào sơ đồ widget của mình thông qua `MultiProvider`, vì GetX sử dụng tính năng nạp dependency của riêng nó, tách hoàn toàn DI khỏi chế độ xem của nó. 81 + GetX cho phép tách toàn bộ View, presentation logic, business logic, nạp dependencies và điều hướng. Bạn không cần "context" để điều hướng giữa các route, vì vậy bạn sẽ độc lập trong sơ đồ widget (trực quan hóa). Bạn không cần "context" để truy cập Controller / Blocs của mình thông qua một InheritedWidget, vì vậy bạn hoàn toàn tách rời presentation logic và business logic ra khỏi lớp trực quan của mình. Bạn không cần phải đưa các Controller / Models / Blocs vào sơ đồ widget của mình thông qua `MultiProvider`, vì GetX sử dụng tính năng nạp dependency của riêng nó, tách hoàn toàn DI khỏi chế độ xem của nó.
82 82
83 Với GetX, bạn biết nơi tìm từng tính năng ứng dụng của mình, với cơ chế clean code theo mặc định. Ngoài việc giúp bảo trì dễ dàng, GetX giúp việc chia sẻ các mô-đun trở thành khả thi trong Flutter. 83 Với GetX, bạn biết nơi tìm từng tính năng ứng dụng của mình, với cơ chế clean code theo mặc định. Ngoài việc giúp bảo trì dễ dàng, GetX giúp việc chia sẻ các mô-đun trở thành khả thi trong Flutter.
84 - BLoC là điểm khởi đầu để tổ chức code trong Flutter, nó tách biệt logic nghiệp vụ với trực quan. GetX nảy sinh từ điều này, không chỉ tách biệt presentation logic mà còn cả business logic. Nạp dependency bổ sung và route cũng được tách ra và lớp dữ liệu cũng biến mất. Bạn sẽ biết mọi thứ ở đâu và sẽ hình dung tất cả những điều này dễ hơn cả "Hello World".  
85 - GetX là cách dễ nhất, thiết thực và có thể mở rộng để xây dựng các ứng dụng hiệu suất cao với Flutter SDK. GetX chứa đựng một hệ sinh thái rộng lớn xung quanh nó hoạt động hoàn hảo cùng nhau, rất dễ dàng cho người mới bắt đầu và nó chính xác cho các chuyên gia. Nó an toàn, ổn định, cập nhật và cung cấp một loạt các API được tích hợp sẵn mà không có trong Flutter SDK mặc định. 84 + BLoC là điểm khởi đầu để tổ chức code trong Flutter, nó tách biệt business logic ra khỏi lớp trực quan hóa (visualization). GetX nảy sinh từ điều này, không chỉ tách biệt presentation logic mà còn cả business logic. Nạp dependency bổ sung và route cũng được tách ra và lớp dữ liệu cũng biến mất. Bạn sẽ biết mọi thứ ở đâu và sẽ hình dung tất cả những điều này dễ hơn cả xây dựng chương trình "Hello World".
  85 + GetX là cách dễ nhất, thiết thực và có thể mở rộng để xây dựng các ứng dụng hiệu suất cao với Flutter SDK. GetX chứa đựng một hệ sinh thái rộng lớn xung quanh nó hoạt động hoàn hảo cùng nhau, rất dễ dàng cho người mới bắt đầu và nó chính xác cho các chuyên gia. Nó an toàn, ổn định, luôn cập nhật và cung cấp một loạt các API được tích hợp sẵn mà không có trong Flutter SDK mặc định.
86 86
87 -- GetX không cồng kềnh và có vô số tính năng cho phép bạn bắt đầu lập trình mà không cần lo lắng về bất cứ điều gì. Đặc biệt, nó cho phép mỗi tính năng này nằm trong các vùng chứa riêng biệt và chỉ được bắt đầu sau khi sử dụng. Nếu bạn chỉ sử dụng quản lý state thì sẽ chỉ có quản lý state được sử dụng. Nếu bạn chỉ sử dụng route, thì GetX không complie quản lý state. 87 +- GetX không cồng kềnh và có vô số tính năng cho phép bạn bắt đầu lập trình mà không cần lo lắng về bất cứ điều gì. Đặc biệt, nó cho phép mỗi tính năng này nằm trong các vùng chứa riêng biệt và chỉ được bắt đầu sau khi sử dụng. Nếu bạn chỉ sử dụng phần quản lý state của GetX thì sẽ chỉ có quản lý state được sử dụng. Nếu bạn chỉ sử dụng route, thì GetX không biên dịch phần quản lý state.
88 88
89 -- GetX có một hệ sinh thái khổng lồ, một cộng đồng lớn, một số lượng lớn cộng tác viên và sẽ được duy trì miễn là Flutter còn tồn tại. GetX có khả năng chạy đồng dạng trên Android, iOS, Web, Mac, Linux, Windows và trên máy chủ của bạn. 89 +- GetX có một hệ sinh thái khổng lồ, một cộng đồng lớn, một số lượng lớn cộng tác viên và sẽ được duy trì miễn là Flutter còn tồn tại. GetX có khả năng chạy cùng một mã (code) trên Android, iOS, Web, Mac, Linux, Windows và trên máy chủ của bạn.
90 **Bạn hoàn toàn có thể sử dụng lại mã của mình trên frontend qua backend với [Get Server](https://github.com/jonataslaw/get_server)**. 90 **Bạn hoàn toàn có thể sử dụng lại mã của mình trên frontend qua backend với [Get Server](https://github.com/jonataslaw/get_server)**.
91 91
92 **Ngoài ra, toàn bộ quá trình phát triển có thể hoàn toàn tự động, cả trên máy chủ và frontend với [Get CLI](https://github.com/jonataslaw/get_cli)**. 92 **Ngoài ra, toàn bộ quá trình phát triển có thể hoàn toàn tự động, cả trên máy chủ và frontend với [Get CLI](https://github.com/jonataslaw/get_cli)**.
93 93
94 **Ngoài ra, nhằm tăng thêm năng suất của bạn, chúng tôi hỗ trợ 94 **Ngoài ra, nhằm tăng thêm năng suất của bạn, chúng tôi hỗ trợ
95 -[extension to VSCode](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets)[extension to Android Studio/Intellij](https://plugins.jetbrains.com/plugin/14975-getx-snippets)** 95 +[tiện ích trên VSCode](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets)[tiện ích cho Android Studio/Intellij](https://plugins.jetbrains.com/plugin/14975-getx-snippets)**
96 96
97 # Cài Đặt 97 # Cài Đặt
98 98
99 -Thêm Get vào pubspec.yaml file: 99 +Thêm Get vào file pubspec.yaml:
100 100
101 ```yaml 101 ```yaml
102 dependencies: 102 dependencies:
@@ -120,12 +120,12 @@ Dự án "counter" được tạo theo mặc định trên dự án mới trên @@ -120,12 +120,12 @@ Dự án "counter" được tạo theo mặc định trên dự án mới trên
120 void main() => runApp(GetMaterialApp(home: Home())); 120 void main() => runApp(GetMaterialApp(home: Home()));
121 ``` 121 ```
122 122
123 -- Chú ý: điều này không sửa đổi MaterialApp của Flutter, GetMaterialApp không phải là MaterialApp được sửa đổi, nó chỉ là một Widget được tạo trước với MaterialApp mặc định là child. Bạn có thể cấu hình điều này theo cách thủ công, nhưng nó chắc chắn là không cần thiết. GetMaterialApp sẽ tạo các route, đưa chúng vào, đưa bản dịch, đưa mọi thứ bạn cần để điều hướng route. Nếu bạn chỉ sử dụng Get để quản lý trạng thái hoặc quản lý phụ thuộc, thì không cần thiết phải sử dụng GetMaterialApp. Tóm lại, GetMaterialApp CHỈ cần thiết cho các route, snacksbar, internationalization, bottomSheets, Dialog và các APIs cấp cao liên quan đến route và không có "context".  
124 -- Chú ý²: Một lần nữa, bước này CHỈ cần thiết nếu bạn sử dụng quản lý route (`Get.to ()`, `Get.back () ', v.v.). Nếu bạn không sử dụng nó thì không cần thực hiện bước 1 123 +- Chú ý: điều này không sửa đổi MaterialApp của Flutter, GetMaterialApp không phải là MaterialApp được sửa đổi, nó chỉ là một Widget được tạo trước với MaterialApp mặc định là child. Bạn có thể cấu hình điều này theo cách thủ công, nhưng nó chắc chắn là không cần thiết. GetMaterialApp sẽ tạo các route, đưa chúng vào, đưa bản dịch, đưa mọi thứ bạn cần để điều hướng route. Nếu bạn chỉ sử dụng Get để quản lý trạng thái hoặc quản lý phụ thuộc, thì không cần thiết phải sử dụng GetMaterialApp. Tóm lại, GetMaterialApp chỉ cần thiết cho các route, snacksbar, internationalization, bottomSheets, Dialog và các APIs cấp cao liên quan đến route và không có "context".
  124 +- Chú ý²: Một lần nữa, bước này chỉ cần thiết nếu bạn sử dụng quản lý route (`Get.to ()`, `Get.back ()`, v.v.). Nếu bạn không sử dụng nó thì không cần thực hiện bước 1
125 125
126 - Bước 2: 126 - Bước 2:
127 - Tạo lớp business logic của bạn và đặt tất cả các variables, function và controller bên trong nó.  
128 - Bạn có thể làm cho bất kỳ variables nào có thể quan sát được bằng cách sử dụng ".obs" đơn giản. 127 + Tạo lớp business logic của bạn và đặt tất cả các biến (variables), hàm (function) và controller bên trong nó.
  128 + Bạn có thể làm cho bất kỳ biến nào có thể quan sát được đơn giản bằng cách sử dụng ".obs".
129 129
130 ```dart 130 ```dart
131 class Controller extends GetxController{ 131 class Controller extends GetxController{
@@ -184,7 +184,7 @@ Cải thiện thời gian, giao mọi thứ đúng hạn mà không làm giảm @@ -184,7 +184,7 @@ Cải thiện thời gian, giao mọi thứ đúng hạn mà không làm giảm
184 184
185 ## Quản lý State 185 ## Quản lý State
186 186
187 -Get has two different state managers: the simple state manager (we'll call it GetBuilder) and the reactive state manager (GetX/Obx) 187 +Get có 2 cách quản lý trạng thái (state managers) khác nhau : quản lý trạng thái đơn giản (chúng ta gọi nó là GetBuilder) và quản lý trạng thái phản ứng (the reactive state manager) (GetX/Obx).
188 188
189 ### Quản lý Reactive State 189 ### Quản lý Reactive State
190 190
@@ -192,7 +192,7 @@ Lập trình phản ứng (reactive programming) có thể khiến nhiều ngư @@ -192,7 +192,7 @@ Lập trình phản ứng (reactive programming) có thể khiến nhiều ngư
192 192
193 - Bạn sẽ không cần tạo StreamControllers. 193 - Bạn sẽ không cần tạo StreamControllers.
194 - Bạn sẽ không cần tạo StreamBuilder cho mỗi biến. 194 - Bạn sẽ không cần tạo StreamBuilder cho mỗi biến.
195 -- Bạn sẽ không cần tạo một lớp cho mỗi trạng thái. 195 +- Bạn sẽ không cần tạo một lớp (class) cho mỗi trạng thái.
196 - Bạn sẽ không cần tạo get cho một giá trị ban đầu. 196 - Bạn sẽ không cần tạo get cho một giá trị ban đầu.
197 - Bạn sẽ không cần sử dụng trình tạo mã. 197 - Bạn sẽ không cần sử dụng trình tạo mã.
198 198
@@ -206,7 +206,7 @@ Hãy tưởng tượng rằng bạn có một biến tên và muốn rằng mỗ @@ -206,7 +206,7 @@ Hãy tưởng tượng rằng bạn có một biến tên và muốn rằng mỗ
206 var name = 'Jonatas Borges'; 206 var name = 'Jonatas Borges';
207 ``` 207 ```
208 208
209 -Để lắng nghe nó, bạn chỉ cần thêm ".obs" ở cuối: 209 +Để nó có thể được lắng nghe, bạn chỉ cần thêm ".obs" ở cuối:
210 210
211 ```dart 211 ```dart
212 var name = 'Jonatas Borges'.obs; 212 var name = 'Jonatas Borges'.obs;
@@ -222,9 +222,9 @@ Thế thôi. Chỉ là _thế_ thôi người ơi~. @@ -222,9 +222,9 @@ Thế thôi. Chỉ là _thế_ thôi người ơi~.
222 222
223 ### Thêm thông tin về Quản lý state 223 ### Thêm thông tin về Quản lý state
224 224
225 -**Xem thông tin cụ thể tại dây [here](./documentation/en_US/state_management.md). Tại đó, bạn có thể tham khảo ví dụ và so sánh sự khác nhau giữa quản lý state cơ bản và quản lý state reactive** 225 +**Xem thông tin cụ thể tại [đây](./documentation/en_US/state_management.md). Tại đó, bạn có thể tham khảo ví dụ và so sánh sự khác nhau giữa quản lý state cơ bản và quản lý state reactive**
226 226
227 -Bạn sẽ hình dung sức mạnh của GetX. 227 +Bạn sẽ hình dung được sức mạnh của GetX.
228 228
229 ## Quản lý route 229 ## Quản lý route
230 230
@@ -245,7 +245,7 @@ Di chuyển tới màn hình mới: @@ -245,7 +245,7 @@ Di chuyển tới màn hình mới:
245 Get.to(NextScreen()); 245 Get.to(NextScreen());
246 ``` 246 ```
247 247
248 -Di chuyển tới màn hình mới theo tên. Xem thêm tại đây [here](./documentation/en_US/route_management.md#navigation-with-named-routes) 248 +Di chuyển tới màn hình mới theo tên. Xem thêm tại [đây](./documentation/en_US/route_management.md#navigation-with-named-routes)
249 249
250 ```dart 250 ```dart
251 251
@@ -274,28 +274,28 @@ Bạn có thấy nãy giờ chúng ta không sử dụng từ khóa "context"? @@ -274,28 +274,28 @@ Bạn có thấy nãy giờ chúng ta không sử dụng từ khóa "context"?
274 274
275 ### Thêm thông tin về quản lý route 275 ### Thêm thông tin về quản lý route
276 276
277 -**Get works with named routes and also offers lower-level control over your routes! There is in-depth documentation [here](./documentation/en_US/route_management.md)** 277 +**Get hoạt động được với named routes và cũng cung cấp cách điều khiển ở cấp thấp (lower-level control) cho routes của bạn! Tài liệu chi tiết tại [đây](./documentation/en_US/route_management.md)**
278 278
279 ## Quản lý dependency 279 ## Quản lý dependency
280 280
281 -Get hỗ trợ tính năng giúp bạn lấy class như Bloc hoặc Controller chỉ với 1 dòng, khỏi cần Provider context hay InheritedWidget: 281 +Get hỗ trợ tính năng giúp bạn lấy class như Bloc hoặc Controller chỉ với 1 dòng, không cần Provider context hay InheritedWidget:
282 282
283 ```dart 283 ```dart
284 Controller controller = Get.put(Controller()); // Rather Controller controller = Controller(); 284 Controller controller = Get.put(Controller()); // Rather Controller controller = Controller();
285 ``` 285 ```
286 286
287 -- Chí ú: Nếu bạn dùng cái này, nhớ đặt attention to thànhe bindings API, which will make it easier to connect your view to your controller. 287 +- Chú ý: Nếu bạn dùng Get's State Manager, hãy chú ý đến việc bindings API, có thể giúp dễ dàng kết nối view đến controller.
288 288
289 Thay vì khởi tạo class của bạn trong class bạn đang sử dụng, bạn đang khởi tạo nó trong phiên bản Get, điều này sẽ làm cho nó có sẵn trên toàn bộ Ứng dụng của bạn. 289 Thay vì khởi tạo class của bạn trong class bạn đang sử dụng, bạn đang khởi tạo nó trong phiên bản Get, điều này sẽ làm cho nó có sẵn trên toàn bộ Ứng dụng của bạn.
290 Vì vậy, bạn có thể sử dụng bộ điều khiển (hoặc Bloc) của mình một cách bình thường 290 Vì vậy, bạn có thể sử dụng bộ điều khiển (hoặc Bloc) của mình một cách bình thường
291 291
292 -**Mẹo:** Nhận quản lý dependency được tách ra khỏi các phần khác của package, vì vậy, ví dụ: nếu ứng dụng của bạn đã sử dụng trình quản lý trạng thái (bất kỳ cái nào, không quan trọng), bạn không cần phải viết lại tất cả, bạn có thể sử dụng điều này nạp dependency vô lo 292 +**Mẹo:** quản lý dependency của Get được tách ra khỏi các phần khác của package, vì vậy, ví dụ: nếu ứng dụng của bạn đã sử dụng 1 trình quản lý trạng thái (bất kỳ cái nào, không quan trọng), bạn không cần phải viết lại tất cả, bạn có thể sử dụng nạp dependency của Get vô lo
293 293
294 ```dart 294 ```dart
295 controller.fetchApi(); 295 controller.fetchApi();
296 ``` 296 ```
297 297
298 -Hãy tưởng tượng rằng bạn đã điều hướng qua nhiều route và bạn cần dữ liệu bị còn sót trong controller của mình, bạn sẽ cần một trình quản lý dependency kết hợp với Provider hoặc Get_it, đúng hơm? Với Get, sử dụng Get to "find" cho controller, bạn sẽ hoàn toàn độc lập: 298 +Hãy tưởng tượng rằng bạn đã điều hướng qua nhiều route và bạn cần dữ liệu bị còn sót trong controller của mình, bạn sẽ cần một trình quản lý dependency kết hợp với Provider hoặc Get_it, đúng không? Với Get, sử dụng Get để "find" cho controller, bạn sẽ hoàn toàn độc lập:
299 299
300 ```dart 300 ```dart
301 Controller controller = Get.find(); 301 Controller controller = Get.find();
@@ -310,7 +310,7 @@ Text(controller.textFromApi); @@ -310,7 +310,7 @@ Text(controller.textFromApi);
310 310
311 ### Thêm thông tin về quản lý dependency 311 ### Thêm thông tin về quản lý dependency
312 312
313 -**Xem thêm tại đây [here](./documentation/en_US/dependency_management.md)** 313 +**Xem thêm tại [đây](./documentation/en_US/dependency_management.md)**
314 314
315 # Utils 315 # Utils
316 316
@@ -318,8 +318,8 @@ Text(controller.textFromApi); @@ -318,8 +318,8 @@ Text(controller.textFromApi);
318 318
319 ### Dịch thuật 319 ### Dịch thuật
320 320
321 -Các bản dịch được lưu giữ như một bản đồ từ điển key-value đơn giản.  
322 -Để thêm các bản dịch tùy chỉnh, hãy tạo một class và extends `Translation`. 321 +Các bản dịch được lưu giữ như một bản đồ từ điển (dictionary map) key-value đơn giản.
  322 +Để thêm các bản dịch tùy chỉnh, hãy tạo một class và kế thừa (extend) từ `Translation`.
323 323
324 ```dart 324 ```dart
325 import 'package:get/get.dart'; 325 import 'package:get/get.dart';
@@ -339,7 +339,7 @@ class Messages extends Translations { @@ -339,7 +339,7 @@ class Messages extends Translations {
339 339
340 #### Sử dụng bản dịch thuật 340 #### Sử dụng bản dịch thuật
341 341
342 -Chỉ cần append `.tr` vào key được chỉ định và nó sẽ được dịch, sử dụng giá trị hiện tại của` Get.locale` và `Get.fallbackLocale`. 342 +Chỉ cần thêm `.tr` vào key được chỉ định và nó sẽ được dịch, sử dụng giá trị hiện tại của` Get.locale` và `Get.fallbackLocale`.
343 343
344 ```dart 344 ```dart
345 Text('title'.tr); 345 Text('title'.tr);
@@ -404,7 +404,7 @@ return GetMaterialApp( @@ -404,7 +404,7 @@ return GetMaterialApp(
404 ); 404 );
405 ``` 405 ```
406 406
407 -## Đổi Theme 407 +## Đổi chủ đề (Theme)
408 408
409 Vui lòng không sử dụng bất kỳ Widget con nào cấp cao hơn `GetMaterialApp` để cập nhật nó. Điều này có thể kích hoạt các key trùng lặp. Rất nhiều người đã quen với cách tiếp cận thời tiền sử là tạo tiện ích "ThemeProvider" chỉ để thay đổi chủ đề ứng dụng của bạn và điều này KHÔNG cần thiết với ** GetX ™ **. 409 Vui lòng không sử dụng bất kỳ Widget con nào cấp cao hơn `GetMaterialApp` để cập nhật nó. Điều này có thể kích hoạt các key trùng lặp. Rất nhiều người đã quen với cách tiếp cận thời tiền sử là tạo tiện ích "ThemeProvider" chỉ để thay đổi chủ đề ứng dụng của bạn và điều này KHÔNG cần thiết với ** GetX ™ **.
410 410
@@ -431,7 +431,7 @@ GetConnect tạo giao thức tới http hoặc websockets @@ -431,7 +431,7 @@ GetConnect tạo giao thức tới http hoặc websockets
431 431
432 ### Cấu hình mặc định 432 ### Cấu hình mặc định
433 433
434 -Đơn giản hóa các lệnh GET/POST/PUT/DELETE/SOCKET khi giao tiếp Rest API hoặc websockets. 434 +Đơn giản, bạn có thể kế thừa (extend) từ GetConnect và sử dụng các phương thức GET/POST/PUT/DELETE/SOCKET khi giao tiếp với Rest API hoặc websockets.
435 435
436 ```dart 436 ```dart
437 class UserProvider extends GetConnect { 437 class UserProvider extends GetConnect {
@@ -454,7 +454,7 @@ class UserProvider extends GetConnect { @@ -454,7 +454,7 @@ class UserProvider extends GetConnect {
454 } 454 }
455 ``` 455 ```
456 456
457 -### Tùy chỉnh 457 +### Cấu hình tùy chỉnh
458 458
459 GetConnect có khả năng tùy chỉnh cao Bạn có thể xác định Url chính như answers, modifiers như request, xác địng authenticator và thậm chí số lần thử mà nó sẽ cố gắng authenticate, ngoài việc cung cấp khả năng xác định bộ giải mã chuẩn sẽ chuyển đổi tất cả các request của bạn thành Model mà không cần bất kỳ cấu hình bổ sung nào. 459 GetConnect có khả năng tùy chỉnh cao Bạn có thể xác định Url chính như answers, modifiers như request, xác địng authenticator và thậm chí số lần thử mà nó sẽ cố gắng authenticate, ngoài việc cung cấp khả năng xác định bộ giải mã chuẩn sẽ chuyển đổi tất cả các request của bạn thành Model mà không cần bất kỳ cấu hình bổ sung nào.
460 460
@@ -507,7 +507,7 @@ class HomeProvider extends GetConnect { @@ -507,7 +507,7 @@ class HomeProvider extends GetConnect {
507 507
508 GetPage hiện có thuộc tính mới lấy danh sách GetMiddleWare và chạy chúng theo thứ tự cụ thể. 508 GetPage hiện có thuộc tính mới lấy danh sách GetMiddleWare và chạy chúng theo thứ tự cụ thể.
509 509
510 -**Chí ú**: Khi GetPage có Middleware (phần trung gian), tất cả các children của trang này sẽ tự động có cùng middlewares. 510 +**Chú ý**: Khi GetPage có Middleware (phần trung gian), tất cả các children của trang này sẽ tự động có cùng middlewares.
511 511
512 ### Ưu tiên 512 ### Ưu tiên
513 513
@@ -549,7 +549,7 @@ GetPage onPageCalled(GetPage page) { @@ -549,7 +549,7 @@ GetPage onPageCalled(GetPage page) {
549 549
550 ### OnBindingsStart 550 ### OnBindingsStart
551 551
552 -Function này sẽ khởi động trước khi Bindinds diễn ra và bạn có thể thay đổi Bindings cho trang này. 552 +Hàm này sẽ khởi động ngay trước khi Bindings diễn ra và bạn có thể thay đổi Bindings cho trang này.
553 553
554 ```dart 554 ```dart
555 List<Bindings> onBindingsStart(List<Bindings> bindings) { 555 List<Bindings> onBindingsStart(List<Bindings> bindings) {
@@ -563,7 +563,7 @@ List<Bindings> onBindingsStart(List<Bindings> bindings) { @@ -563,7 +563,7 @@ List<Bindings> onBindingsStart(List<Bindings> bindings) {
563 563
564 ### OnPageBuildStart 564 ### OnPageBuildStart
565 565
566 -Function này sẽ khởi động sau khi Bindings diễn ra. Ở đây, bạn có thể làm thứ gì đó sau khi bạn tạo Bindings và trước khi tạo trange widget. 566 +Hàm này sẽ khởi động ngay sau khi Bindings diễn ra. Ở đây, bạn có thể làm thứ gì đó sau khi bạn tạo Bindings và trước khi tạo trang widget.
567 567
568 ```dart 568 ```dart
569 GetPageBuilder onPageBuildStart(GetPageBuilder page) { 569 GetPageBuilder onPageBuildStart(GetPageBuilder page) {
@@ -574,7 +574,7 @@ GetPageBuilder onPageBuildStart(GetPageBuilder page) { @@ -574,7 +574,7 @@ GetPageBuilder onPageBuildStart(GetPageBuilder page) {
574 574
575 ### OnPageBuilt 575 ### OnPageBuilt
576 576
577 -Function này sẽ khởi động ngay sau khi GetPage.page được gọi và sẽ cho bạn kết quả của function và lấy widget được hiển thị. 577 +Hàm này sẽ khởi động ngay sau khi GetPage.page được gọi và sẽ cho bạn kết quả của hàm và lấy widget được hiển thị.
578 578
579 ### OnPageDispose 579 ### OnPageDispose
580 580
@@ -723,7 +723,7 @@ MaterialApp( @@ -723,7 +723,7 @@ MaterialApp(
723 ); 723 );
724 ``` 724 ```
725 725
726 -You will also be able to use your own Middleware within `GetObserver`, this will not influence anything. 726 +Bạn cũng sẽ có thể dùng Middleware của riêng bạn trong `GetObserver`, điều này không ảnh hưởng những thứ khác.
727 727
728 ```dart 728 ```dart
729 MaterialApp( 729 MaterialApp(
@@ -734,8 +734,8 @@ MaterialApp( @@ -734,8 +734,8 @@ MaterialApp(
734 ); 734 );
735 ``` 735 ```
736 736
737 -You can create _Global Settings_ for `Get`. Just add `Get.config` to your code before pushing any route.  
738 -Or do it directly in your `GetMaterialApp` 737 +Bạn có thể tạo _Global Settings_ cho `Get`. Chỉ cần thêm `Get.config` vào code của bạn trước khi đẩy (push) bất cứ route nào.
  738 +Hoặc làm nó trực tiếp trong `GetMaterialApp` của bạn.
739 739
740 ```dart 740 ```dart
741 GetMaterialApp( 741 GetMaterialApp(
@@ -754,9 +754,8 @@ Get.config( @@ -754,9 +754,8 @@ Get.config(
754 ) 754 )
755 ``` 755 ```
756 756
757 -You can optionally redirect all the logging messages from `Get`.  
758 -If you want to use your own, favourite logging package,  
759 -and want to capture the logs there: 757 +Bạn có thể tự chọn chuyển hướng tất cả logging messages từ `Get`.
  758 +Nếu bạn muốn sử dụng logging package ưa thích của riêng bạn, và muốn chụp lại những logs đó:
760 759
761 ```dart 760 ```dart
762 GetMaterialApp( 761 GetMaterialApp(
@@ -775,7 +774,7 @@ void localLogWriter(String text, {bool isError = false}) { @@ -775,7 +774,7 @@ void localLogWriter(String text, {bool isError = false}) {
775 ### Local State Widgets 774 ### Local State Widgets
776 775
777 Các Widget này cho phép bạn quản lý một giá trị duy nhất và giữ trạng thái tạm thời và cục bộ. 776 Các Widget này cho phép bạn quản lý một giá trị duy nhất và giữ trạng thái tạm thời và cục bộ.
778 -Chúng tôi có các hướng đi cho Reactive và Simple. 777 +Chúng ta có các hướng đi cho Reactive và Simple.
779 Ví dụ: bạn có thể sử dụng chúng để chuyển đổi văn bản tối nghĩa trong một `TextField`, có thể tạo một widget 778 Ví dụ: bạn có thể sử dụng chúng để chuyển đổi văn bản tối nghĩa trong một `TextField`, có thể tạo một widget
780 Expandable Panel tùy chỉnh hoặc có thể sửa đổi chỉ mục hiện tại trong `BottomNavigationBar` trong khi thay đổi nội dung 779 Expandable Panel tùy chỉnh hoặc có thể sửa đổi chỉ mục hiện tại trong `BottomNavigationBar` trong khi thay đổi nội dung
781 bên trong một `Scaffold`. 780 bên trong một `Scaffold`.
@@ -799,7 +798,7 @@ ValueBuilder<bool>( @@ -799,7 +798,7 @@ ValueBuilder<bool>(
799 798
800 #### ObxValue 799 #### ObxValue
801 800
802 -Tương tự như [`ValueBuilder`] (# valuebuilder), nhưng đây là phiên bản Reactive, bạn kèm một lệnh Rx (nhớ cái .obs không?) và nó cập nhật tự động ... hay chưa? 801 +Tương tự như [`ValueBuilder`](#valuebuilder), nhưng đây là phiên bản Reactive, bạn kèm một lệnh Rx (nhớ cái .obs không?) và nó cập nhật tự động ... hay chưa?
803 802
804 ```dart 803 ```dart
805 ObxValue((data) => Switch( 804 ObxValue((data) => Switch(
@@ -823,7 +822,7 @@ var message = 'Xin Chào'.obs; @@ -823,7 +822,7 @@ var message = 'Xin Chào'.obs;
823 print( 'Message "$message" has Type ${message.runtimeType}'); 822 print( 'Message "$message" has Type ${message.runtimeType}');
824 ``` 823 ```
825 824
826 -Ngay cả khi `message` _prints_ giá trị String, Loại là ** RxString **! 825 +Ngay cả khi `message` _prints_ giá trị String, thì kiểu của nó lại là ** RxString **!
827 826
828 Vì vậy, bạn không thể thực hiện `message.substring (0, 4) '. Bạn phải truy cập vào `value`thực bên trong _observable_: Cách được sử dụng nhiều nhất là`.value`, nhưng, bạn có biết rằng bạn cũng có thể sử dụng ... 827 Vì vậy, bạn không thể thực hiện `message.substring (0, 4) '. Bạn phải truy cập vào `value`thực bên trong _observable_: Cách được sử dụng nhiều nhất là`.value`, nhưng, bạn có biết rằng bạn cũng có thể sử dụng ...
829 828
@@ -917,20 +916,20 @@ print( user ); @@ -917,20 +916,20 @@ print( user );
917 ## StateMixin 916 ## StateMixin
918 917
919 Một cách khác để xử lý trạng thái `UI` của bạn là sử dụng`StateMixin <T>`. 918 Một cách khác để xử lý trạng thái `UI` của bạn là sử dụng`StateMixin <T>`.
920 -Để triển khai nó, hãy sử dụng dấu `with` để thêm`StateMixin <T>` bộ điều khiển của bạn cho phép tích hợp kèm mô hình T. 919 +Để triển khai nó, hãy sử dụng dấu `with` để thêm`StateMixin <T>` vào bộ điều khiển (controller) của bạn cho phép tích hợp kèm mô hình T.
921 920
922 ```dart 921 ```dart
923 class Controller extends GetController with StateMixin<User>{} 922 class Controller extends GetController with StateMixin<User>{}
924 ``` 923 ```
925 924
926 -Phương thức `change ()` thay đổi trạng thái bất cứ khi nào chúng ta muốn. 925 +Phương thức `change()` thay đổi trạng thái bất cứ khi nào chúng ta muốn.
927 Chỉ cần chuyển dữ liệu và trạng thái theo cách này: 926 Chỉ cần chuyển dữ liệu và trạng thái theo cách này:
928 927
929 ```dart 928 ```dart
930 change(data, status: RxStatus.success()); 929 change(data, status: RxStatus.success());
931 ``` 930 ```
932 931
933 -RxStatus allow these status: 932 +RxStatus cho phép những trang thái này:
934 933
935 ```dart 934 ```dart
936 RxStatus.loading(); 935 RxStatus.loading();
@@ -939,7 +938,7 @@ RxStatus.empty(); @@ -939,7 +938,7 @@ RxStatus.empty();
939 RxStatus.error('message'); 938 RxStatus.error('message');
940 ``` 939 ```
941 940
942 -To represent it in the UI, use: 941 +Để biểu hiện nó trên UI, sử dụng:
943 942
944 ```dart 943 ```dart
945 class OtherClass extends GetView<Controller> { 944 class OtherClass extends GetView<Controller> {
@@ -965,7 +964,7 @@ class OtherClass extends GetView<Controller> { @@ -965,7 +964,7 @@ class OtherClass extends GetView<Controller> {
965 964
966 #### GetView 965 #### GetView
967 966
968 -Widget này là bảo bối của Getx, rất đơn giản, nhưng rất hữu ích! 967 +Widget này là bảo bối của GetX, rất đơn giản, nhưng rất hữu ích!
969 968
970 Là một Widget `const Stateless` có getter` controller` cho một `Controller` đã đăng ký, chỉ vậy thôi người ơi~. 969 Là một Widget `const Stateless` có getter` controller` cho một `Controller` đã đăng ký, chỉ vậy thôi người ơi~.
971 970
@@ -989,7 +988,7 @@ Là một Widget `const Stateless` có getter` controller` cho một `Controller @@ -989,7 +988,7 @@ Là một Widget `const Stateless` có getter` controller` cho một `Controller
989 #### GetResponsiveView 988 #### GetResponsiveView
990 989
991 Mở rộng tiện ích này để xây dựng chế độ responsive. 990 Mở rộng tiện ích này để xây dựng chế độ responsive.
992 -Ưidget này chứa thuộc tính `screen` có tất cả 991 +Widget này chứa thuộc tính `screen` có tất cả
993 thông tin về kích thước và loại màn hình. 992 thông tin về kích thước và loại màn hình.
994 993
995 ##### Hướng dẫn sử dụng trước khi dùng 994 ##### Hướng dẫn sử dụng trước khi dùng
@@ -998,9 +997,9 @@ Bạn có hai lựa chọn để xây dựng nó. @@ -998,9 +997,9 @@ Bạn có hai lựa chọn để xây dựng nó.
998 997
999 - với phương thức `builder` bạn trả về tiện ích con để xây dựng. 998 - với phương thức `builder` bạn trả về tiện ích con để xây dựng.
1000 - với các phương thức `desktop`,` tablet`, `phone`,` watch`. cụ thể, các phương thức này sẽ tạo các loại màn hình khớp với ngữ cảnh khi màn hình là [ScreenType.Tablet] thì phương thức `tablet` sẽ được tạo ra và cứ như vậy. 999 - với các phương thức `desktop`,` tablet`, `phone`,` watch`. cụ thể, các phương thức này sẽ tạo các loại màn hình khớp với ngữ cảnh khi màn hình là [ScreenType.Tablet] thì phương thức `tablet` sẽ được tạo ra và cứ như vậy.
1001 - **Chí ú:** Nếu bạn dùng cái này, nhớ đặt `alwaysUseBuilder` thành `false` 1000 + **Chú ý:** Nếu bạn dùng cái này, nhớ đặt `alwaysUseBuilder` thành `false`
1002 1001
1003 -Với `settings` property bạn có thể đặt chiều dài tối thiểu cho các loại màn hình. 1002 +Với thuộc tính `settings` bạn có thể đặt chiều dài tối thiểu cho các loại màn hình.
1004 1003
1005 ![example](https://github.com/SchabanBo/get_page_example/blob/master/docs/Example.gif?raw=true) 1004 ![example](https://github.com/SchabanBo/get_page_example/blob/master/docs/Example.gif?raw=true)
1006 Code to this screen 1005 Code to this screen
@@ -1012,13 +1011,13 @@ Hầu hết mọi người không biết gì về Widget này, hoặc hoàn toà @@ -1012,13 +1011,13 @@ Hầu hết mọi người không biết gì về Widget này, hoặc hoàn toà
1012 Trường hợp sử dụng rất hiếm, nhưng rất cụ thể: Nó `caches` một Bộ điều khiển. 1011 Trường hợp sử dụng rất hiếm, nhưng rất cụ thể: Nó `caches` một Bộ điều khiển.
1013 Bởi vì _cache_ không thể là một `const Stateless`. 1012 Bởi vì _cache_ không thể là một `const Stateless`.
1014 1013
1015 -> So, when do you need to "cache" a Controller? 1014 +> Vậy khi nào mình cần cache bộ điều khiển (controller)?
1016 1015
1017 Nếu sử dụng, bạn sẽ dùng cái này **GetX**: `Get.create()`. 1016 Nếu sử dụng, bạn sẽ dùng cái này **GetX**: `Get.create()`.
1018 1017
1019 `Get.create(()=>Controller())` sẽ tạo một `Controller` với mỗi lần gọi `Get.find<Controller>()`, 1018 `Get.create(()=>Controller())` sẽ tạo một `Controller` với mỗi lần gọi `Get.find<Controller>()`,
1020 1019
1021 -Đó là nơi mà `` GetWidget` tỏa sáng ... chẳng hạn như bạn có thể sử dụng nó, để giữ một danh sách các mục Todo. Vì vậy, nếu widget được "xây dựng lại", nó sẽ giữ nguyên phiên bản controller. 1020 +Đó là nơi mà `GetWidget` tỏa sáng ... chẳng hạn như bạn có thể sử dụng nó, để giữ một danh sách các mục Todo. Vì vậy, nếu widget được "xây dựng lại", nó sẽ giữ nguyên phiên bản controller.
1022 1021
1023 #### GetxService 1022 #### GetxService
1024 1023
@@ -1066,7 +1065,7 @@ class SettingsService extends GetxService { @@ -1066,7 +1065,7 @@ class SettingsService extends GetxService {
1066 1065
1067 ``` 1066 ```
1068 1067
1069 -Cách duy nhất để thực sự xóa một `GetxService`, là với`Get.reset ()`giống như cách thức "Khởi động nóng" ứng dụng của bạn. Vì vậy, hãy nhớ rằng, nếu bạn cần sự tồn tại tuyệt đối của một class trong vòng đời tồn tại của nó trong ứng dụng của bạn, hãy sử dụng `GetxService`. 1068 +Cách duy nhất để thực sự xóa một `GetxService`, là với `Get.reset ()` giống như cách thức "Khởi động nóng" ứng dụng của bạn. Vì vậy, hãy nhớ rằng, nếu bạn cần sự tồn tại tuyệt đối của một class trong vòng đời tồn tại của nó trong ứng dụng của bạn, hãy sử dụng `GetxService`.
1070 1069
1071 # Thay đổi đột phá 2.0 1070 # Thay đổi đột phá 2.0
1072 1071
@@ -1130,7 +1129,7 @@ GetMaterialApp( @@ -1130,7 +1129,7 @@ GetMaterialApp(
1130 3- Dễ dàng mà không phải lo lắng về hiệu suất. Hiệu suất của Flutter đã đáng kinh ngạc rồi, nhưng hãy tưởng tượng rằng bạn sử dụng trình quản lý state và trình định vị để phân phối các Blocs / stores / controllers / v.v. của bạn. Bạn sẽ phải gọi thủ công loại trừ sự phụ thuộc khi bạn không cần đến chúng. Nhưng bạn đã bao giờ nghĩ chỉ cần sử dụng bộ điều khiển của mình và khi nó không còn được ai sử dụng nữa, nó sẽ đơn giản được xóa khỏi bộ nhớ? Đó là những gì GetX làm. Với SmartManagement, mọi thứ không được sử dụng sẽ được xóa khỏi bộ nhớ và bạn không phải lo lắng về bất cứ điều gì ngoài lập trình. Bạn sẽ được đảm bảo rằng bạn đang sử dụng các nguồn tài nguyên cần thiết tối thiểu mà thậm chí không cần tạo ra một logic nào cho việc này. 1129 3- Dễ dàng mà không phải lo lắng về hiệu suất. Hiệu suất của Flutter đã đáng kinh ngạc rồi, nhưng hãy tưởng tượng rằng bạn sử dụng trình quản lý state và trình định vị để phân phối các Blocs / stores / controllers / v.v. của bạn. Bạn sẽ phải gọi thủ công loại trừ sự phụ thuộc khi bạn không cần đến chúng. Nhưng bạn đã bao giờ nghĩ chỉ cần sử dụng bộ điều khiển của mình và khi nó không còn được ai sử dụng nữa, nó sẽ đơn giản được xóa khỏi bộ nhớ? Đó là những gì GetX làm. Với SmartManagement, mọi thứ không được sử dụng sẽ được xóa khỏi bộ nhớ và bạn không phải lo lắng về bất cứ điều gì ngoài lập trình. Bạn sẽ được đảm bảo rằng bạn đang sử dụng các nguồn tài nguyên cần thiết tối thiểu mà thậm chí không cần tạo ra một logic nào cho việc này.
1131 1130
1132 4- Tách khỏi thực tế. Bạn có thể đã nghe đến khái niệm "tách khung nhìn (view) khỏi business logic". Đây không phải là đặc thù của BLoC, MVC, MVVM và bất kỳ tiêu chuẩn nào khác trên thị trường đều có khái niệm này. Tuy nhiên, khái niệm này thường có thể được giảm thiểu trong Flutter do việc sử dụng ngữ cảnh (context). 1131 4- Tách khỏi thực tế. Bạn có thể đã nghe đến khái niệm "tách khung nhìn (view) khỏi business logic". Đây không phải là đặc thù của BLoC, MVC, MVVM và bất kỳ tiêu chuẩn nào khác trên thị trường đều có khái niệm này. Tuy nhiên, khái niệm này thường có thể được giảm thiểu trong Flutter do việc sử dụng ngữ cảnh (context).
1133 -Nếu bạn cần ngữ cảnh để tìm một InheritedWidget, bạn cần nó trong dạng xem hoặc chuyển ngữ cảnh theo tham số. Tôi đặc biệt thấy giải pháp này rất chán đời; hơn nữa, để làm việc theo nhóm, chúng tôi sẽ luôn phụ thuộc vào business logic của View. Getx không chính thống với cách tiếp cận tiêu chuẩn và mặc dù nó không cấm hoàn toàn việc sử dụng StatefulWidgets, InitState, v.v., nhưng nó luôn có một cách tiếp cận tương tự có thể rõ ràng hơn. Controller có vòng đời và khi bạn cần thực hiện yêu cầu APIREST chẳng hạn, bạn độc lập với View. Bạn có thể sử dụng onInit để bắt đầu cuộc gọi http và khi dữ liệu đến, các biến sẽ được điền. Vì GetX hoạt động hoàn toàn reactive (đó là sự thực và hoạt động theo luồng), khi các mục được lấp đầy, tất cả tiện ích con sử dụng biến đó sẽ được cập nhật tự động trong View. Điều này cho phép những người có chuyên môn về UI chỉ làm việc với các widget và không phải gửi bất kỳ thứ gì đến logic nghiệp vụ ngoài các sự kiện của người dùng (như nhấp vào nút), trong khi những người làm việc với logic nghiệp vụ sẽ được tự do tạo và kiểm tra logic nghiệp vụ riêng. 1132 +Nếu bạn cần ngữ cảnh để tìm một InheritedWidget, bạn cần nó trong dạng xem hoặc chuyển ngữ cảnh theo tham số. Tôi đặc biệt thấy giải pháp này rất chán đời; hơn nữa, để làm việc theo nhóm, chúng tôi sẽ luôn phụ thuộc vào business logic của View. GetX không chính thống với cách tiếp cận tiêu chuẩn và mặc dù nó không cấm hoàn toàn việc sử dụng StatefulWidgets, InitState, v.v., nhưng nó luôn có một cách tiếp cận tương tự có thể rõ ràng hơn. Controller có vòng đời và khi bạn cần thực hiện yêu cầu APIREST chẳng hạn, bạn độc lập với View. Bạn có thể sử dụng onInit để bắt đầu cuộc gọi http và khi dữ liệu đến, các biến sẽ được điền. Vì GetX hoạt động hoàn toàn reactive (đó là sự thực và hoạt động theo luồng), khi các mục được lấp đầy, tất cả tiện ích con sử dụng biến đó sẽ được cập nhật tự động trong View. Điều này cho phép những người có chuyên môn về UI chỉ làm việc với các widget và không phải gửi bất kỳ thứ gì đến logic nghiệp vụ ngoài các sự kiện của người dùng (như nhấp vào nút), trong khi những người làm việc với logic nghiệp vụ sẽ được tự do tạo và kiểm tra logic nghiệp vụ riêng.
1134 1133
1135 Thư viện này sẽ luôn được cập nhật và triển khai các tính năng mới. Hãy thoải mái đưa ra các bài PR và đóng góp cho chúng. 1134 Thư viện này sẽ luôn được cập nhật và triển khai các tính năng mới. Hãy thoải mái đưa ra các bài PR và đóng góp cho chúng.
1136 1135
@@ -1158,7 +1157,7 @@ Mọi đóng góp đều được hoan nghênh! @@ -1158,7 +1157,7 @@ Mọi đóng góp đều được hoan nghênh!
1158 1157
1159 ## Các bài báo và video 1158 ## Các bài báo và video
1160 1159
1161 -- [Flutter Getx EcoSystem package for arabic people](https://www.youtube.com/playlist?list=PLV1fXIAyjeuZ6M8m56zajMUwu4uE3-SL0) - Hướng dẫn bởi [Pesa Coder](https://github.com/UsamaElgendy). 1160 +- [Flutter GetX EcoSystem package for arabic people](https://www.youtube.com/playlist?list=PLV1fXIAyjeuZ6M8m56zajMUwu4uE3-SL0) - Hướng dẫn bởi [Pesa Coder](https://github.com/UsamaElgendy).
1162 - [Dynamic Themes in 3 lines using GetX™](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Hướng dẫn bởi [Rod Brown](https://github.com/RodBr). 1161 - [Dynamic Themes in 3 lines using GetX™](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Hướng dẫn bởi [Rod Brown](https://github.com/RodBr).
1163 - [Complete GetX™ Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI) - Quản lý route bởi Amateur Coder. 1162 - [Complete GetX™ Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI) - Quản lý route bởi Amateur Coder.
1164 - [Complete GetX State Management](https://www.youtube.com/watch?v=CNpXbeI_slw) - Quản lý State video by Amateur Coder. 1163 - [Complete GetX State Management](https://www.youtube.com/watch?v=CNpXbeI_slw) - Quản lý State video by Amateur Coder.
@@ -205,6 +205,7 @@ class GetHttpClient { @@ -205,6 +205,7 @@ class GetHttpClient {
205 if (authenticate) await _modifier.authenticator!(request); 205 if (authenticate) await _modifier.authenticator!(request);
206 final newRequest = await _modifier.modifyRequest<T>(request); 206 final newRequest = await _modifier.modifyRequest<T>(request);
207 207
  208 + _httpClient.timeout = timeout;
208 var response = await _httpClient.send<T>(newRequest); 209 var response = await _httpClient.send<T>(newRequest);
209 210
210 final newResponse = 211 final newResponse =
@@ -23,6 +23,9 @@ class HttpRequestImpl implements HttpRequestBase { @@ -23,6 +23,9 @@ class HttpRequestImpl implements HttpRequestBase {
23 ///on different sites. The default is false 23 ///on different sites. The default is false
24 final bool withCredentials; 24 final bool withCredentials;
25 25
  26 + @override
  27 + Duration? timeout;
  28 +
26 /// Sends an HTTP request and asynchronously returns the response. 29 /// Sends an HTTP request and asynchronously returns the response.
27 @override 30 @override
28 Future<Response<T>> send<T>(Request<T> request) async { 31 Future<Response<T>> send<T>(Request<T> request) async {
@@ -30,6 +33,7 @@ class HttpRequestImpl implements HttpRequestBase { @@ -30,6 +33,7 @@ class HttpRequestImpl implements HttpRequestBase {
30 html.HttpRequest xhr; 33 html.HttpRequest xhr;
31 34
32 xhr = html.HttpRequest() 35 xhr = html.HttpRequest()
  36 + ..timeout = timeout?.inMilliseconds
33 ..open(request.method, '${request.url}', async: true); // check this 37 ..open(request.method, '${request.url}', async: true); // check this
34 38
35 _xhrs.add(xhr); 39 _xhrs.add(xhr);
@@ -8,4 +8,12 @@ abstract class HttpRequestBase { @@ -8,4 +8,12 @@ abstract class HttpRequestBase {
8 8
9 /// Closes the [Request] and cleans up any resources associated with it. 9 /// Closes the [Request] and cleans up any resources associated with it.
10 void close(); 10 void close();
  11 +
  12 + /// Gets and sets the timeout.
  13 + ///
  14 + /// For mobile, this value will be applied for both connection and request
  15 + /// timeout.
  16 + ///
  17 + /// For web, this value will be the request timeout.
  18 + Duration? timeout;
11 } 19 }
@@ -34,16 +34,20 @@ class HttpRequestImpl extends HttpRequestBase { @@ -34,16 +34,20 @@ class HttpRequestImpl extends HttpRequestBase {
34 @override 34 @override
35 Future<Response<T>> send<T>(Request<T> request) async { 35 Future<Response<T>> send<T>(Request<T> request) async {
36 var stream = request.bodyBytes.asBroadcastStream(); 36 var stream = request.bodyBytes.asBroadcastStream();
37 - 37 + io.HttpClientRequest? ioRequest;
38 try { 38 try {
39 - var ioRequest = (await _httpClient!.openUrl(request.method, request.url)) 39 + _httpClient!.connectionTimeout = timeout;
  40 + ioRequest = (await _httpClient!.openUrl(request.method, request.url))
40 ..followRedirects = request.followRedirects 41 ..followRedirects = request.followRedirects
41 ..persistentConnection = request.persistentConnection 42 ..persistentConnection = request.persistentConnection
42 ..maxRedirects = request.maxRedirects 43 ..maxRedirects = request.maxRedirects
43 ..contentLength = request.contentLength ?? -1; 44 ..contentLength = request.contentLength ?? -1;
44 request.headers.forEach(ioRequest.headers.set); 45 request.headers.forEach(ioRequest.headers.set);
45 46
46 - var response = await stream.pipe(ioRequest) as io.HttpClientResponse; 47 + var response = timeout == null
  48 + ? await stream.pipe(ioRequest) as io.HttpClientResponse
  49 + : await stream.pipe(ioRequest).timeout(timeout!)
  50 + as io.HttpClientResponse;
47 51
48 var headers = <String, String>{}; 52 var headers = <String, String>{};
49 response.headers.forEach((key, values) { 53 response.headers.forEach((key, values) {
@@ -68,6 +72,9 @@ class HttpRequestImpl extends HttpRequestBase { @@ -68,6 +72,9 @@ class HttpRequestImpl extends HttpRequestBase {
68 body: body, 72 body: body,
69 bodyString: stringBody, 73 bodyString: stringBody,
70 ); 74 );
  75 + } on TimeoutException catch (_) {
  76 + ioRequest?.abort();
  77 + rethrow;
71 } on io.HttpException catch (error) { 78 } on io.HttpException catch (error) {
72 throw GetHttpException(error.message, error.uri); 79 throw GetHttpException(error.message, error.uri);
73 } 80 }
@@ -384,7 +384,6 @@ class GetInstance { @@ -384,7 +384,6 @@ class GetInstance {
384 } 384 }
385 385
386 if (builder.fenix) { 386 if (builder.fenix) {
387 - //TODO: Remove if is late remove  
388 builder.dependency = null; 387 builder.dependency = null;
389 builder.isInit = false; 388 builder.isInit = false;
390 return true; 389 return true;
@@ -539,6 +539,7 @@ extension GetNavigation on GetInterface { @@ -539,6 +539,7 @@ extension GetNavigation on GetInterface {
539 Curve? curve, 539 Curve? curve,
540 Duration? duration, 540 Duration? duration,
541 int? id, 541 int? id,
  542 + String? routeName,
542 bool fullscreenDialog = false, 543 bool fullscreenDialog = false,
543 dynamic arguments, 544 dynamic arguments,
544 Bindings? binding, 545 Bindings? binding,
@@ -546,18 +547,20 @@ extension GetNavigation on GetInterface { @@ -546,18 +547,20 @@ extension GetNavigation on GetInterface {
546 bool? popGesture, 547 bool? popGesture,
547 double Function(BuildContext context)? gestureWidth, 548 double Function(BuildContext context)? gestureWidth,
548 }) { 549 }) {
549 - var routeName = "/${page.runtimeType.toString()}"; 550 + // var routeName = "/${page.runtimeType}";
  551 + routeName ??= "/${page.runtimeType}";
  552 + routeName = _cleanRouteName(routeName);
550 if (preventDuplicates && routeName == currentRoute) { 553 if (preventDuplicates && routeName == currentRoute) {
551 return null; 554 return null;
552 } 555 }
553 return global(id).currentState?.push<T>( 556 return global(id).currentState?.push<T>(
554 GetPageRoute<T>( 557 GetPageRoute<T>(
555 opaque: opaque ?? true, 558 opaque: opaque ?? true,
556 - page: _resolve(page, 'to'), 559 + page: _resolvePage(page, 'to'),
557 routeName: routeName, 560 routeName: routeName,
558 gestureWidth: gestureWidth, 561 gestureWidth: gestureWidth,
559 settings: RouteSettings( 562 settings: RouteSettings(
560 - // name: forceRouteName ? '${a.runtimeType}' : '', 563 + name: routeName,
561 arguments: arguments, 564 arguments: arguments,
562 ), 565 ),
563 popGesture: popGesture ?? defaultPopGesture, 566 popGesture: popGesture ?? defaultPopGesture,
@@ -570,7 +573,7 @@ extension GetNavigation on GetInterface { @@ -570,7 +573,7 @@ extension GetNavigation on GetInterface {
570 ); 573 );
571 } 574 }
572 575
573 - GetPageBuilder _resolve(dynamic page, String method) { 576 + GetPageBuilder _resolvePage(dynamic page, String method) {
574 if (page is GetPageBuilder) { 577 if (page is GetPageBuilder) {
575 return page; 578 return page;
576 } else if (page is Widget) { 579 } else if (page is Widget) {
@@ -909,6 +912,7 @@ you can only use widgets and widget functions here'''; @@ -909,6 +912,7 @@ you can only use widgets and widget functions here''';
909 Curve? curve, 912 Curve? curve,
910 bool? popGesture, 913 bool? popGesture,
911 int? id, 914 int? id,
  915 + String? routeName,
912 dynamic arguments, 916 dynamic arguments,
913 Bindings? binding, 917 Bindings? binding,
914 bool fullscreenDialog = false, 918 bool fullscreenDialog = false,
@@ -916,16 +920,20 @@ you can only use widgets and widget functions here'''; @@ -916,16 +920,20 @@ you can only use widgets and widget functions here''';
916 Duration? duration, 920 Duration? duration,
917 double Function(BuildContext context)? gestureWidth, 921 double Function(BuildContext context)? gestureWidth,
918 }) { 922 }) {
919 - var routeName = "/${page.runtimeType.toString()}"; 923 + routeName ??= "/${page.runtimeType.toString()}";
  924 + routeName = _cleanRouteName(routeName);
920 if (preventDuplicates && routeName == currentRoute) { 925 if (preventDuplicates && routeName == currentRoute) {
921 return null; 926 return null;
922 } 927 }
923 return global(id).currentState?.pushReplacement(GetPageRoute( 928 return global(id).currentState?.pushReplacement(GetPageRoute(
924 opaque: opaque, 929 opaque: opaque,
925 gestureWidth: gestureWidth, 930 gestureWidth: gestureWidth,
926 - page: _resolve(page, 'off'), 931 + page: _resolvePage(page, 'off'),
927 binding: binding, 932 binding: binding,
928 - settings: RouteSettings(arguments: arguments), 933 + settings: RouteSettings(
  934 + arguments: arguments,
  935 + name: routeName,
  936 + ),
929 routeName: routeName, 937 routeName: routeName,
930 fullscreenDialog: fullscreenDialog, 938 fullscreenDialog: fullscreenDialog,
931 popGesture: popGesture ?? defaultPopGesture, 939 popGesture: popGesture ?? defaultPopGesture,
@@ -934,7 +942,6 @@ you can only use widgets and widget functions here'''; @@ -934,7 +942,6 @@ you can only use widgets and widget functions here''';
934 transitionDuration: duration ?? defaultTransitionDuration)); 942 transitionDuration: duration ?? defaultTransitionDuration));
935 } 943 }
936 944
937 - /// **Navigation.pushAndRemoveUntil()** shortcut .<br><br>  
938 /// 945 ///
939 /// Push a `page` and pop several pages in the stack 946 /// Push a `page` and pop several pages in the stack
940 /// until [predicate] returns true. [predicate] is optional 947 /// until [predicate] returns true. [predicate] is optional
@@ -971,6 +978,7 @@ you can only use widgets and widget functions here'''; @@ -971,6 +978,7 @@ you can only use widgets and widget functions here''';
971 bool opaque = false, 978 bool opaque = false,
972 bool? popGesture, 979 bool? popGesture,
973 int? id, 980 int? id,
  981 + String? routeName,
974 dynamic arguments, 982 dynamic arguments,
975 Bindings? binding, 983 Bindings? binding,
976 bool fullscreenDialog = false, 984 bool fullscreenDialog = false,
@@ -979,16 +987,19 @@ you can only use widgets and widget functions here'''; @@ -979,16 +987,19 @@ you can only use widgets and widget functions here''';
979 Duration? duration, 987 Duration? duration,
980 double Function(BuildContext context)? gestureWidth, 988 double Function(BuildContext context)? gestureWidth,
981 }) { 989 }) {
982 - var routeName = "/${page.runtimeType.toString()}";  
983 - 990 + routeName ??= "/${page.runtimeType.toString()}";
  991 + routeName = _cleanRouteName(routeName);
984 return global(id).currentState?.pushAndRemoveUntil<T>( 992 return global(id).currentState?.pushAndRemoveUntil<T>(
985 GetPageRoute<T>( 993 GetPageRoute<T>(
986 opaque: opaque, 994 opaque: opaque,
987 popGesture: popGesture ?? defaultPopGesture, 995 popGesture: popGesture ?? defaultPopGesture,
988 - page: _resolve(page, 'offAll'), 996 + page: _resolvePage(page, 'offAll'),
989 binding: binding, 997 binding: binding,
990 gestureWidth: gestureWidth, 998 gestureWidth: gestureWidth,
991 - settings: RouteSettings(arguments: arguments), 999 + settings: RouteSettings(
  1000 + name: routeName,
  1001 + arguments: arguments,
  1002 + ),
992 fullscreenDialog: fullscreenDialog, 1003 fullscreenDialog: fullscreenDialog,
993 routeName: routeName, 1004 routeName: routeName,
994 transition: transition ?? defaultTransition, 1005 transition: transition ?? defaultTransition,
@@ -998,6 +1009,21 @@ you can only use widgets and widget functions here'''; @@ -998,6 +1009,21 @@ you can only use widgets and widget functions here''';
998 predicate ?? (route) => false); 1009 predicate ?? (route) => false);
999 } 1010 }
1000 1011
  1012 + /// Takes a route [name] String generated by [to], [off], [offAll]
  1013 + /// (and similar context navigation methods), cleans the extra chars and
  1014 + /// accommodates the format.
  1015 + /// TODO: check for a more "appealing" URL naming convention.
  1016 + /// `() => MyHomeScreenView` becomes `/my-home-screen-view`.
  1017 + String _cleanRouteName(String name) {
  1018 + name = name.replaceAll('() => ', '');
  1019 + /// uncommonent for URL styling.
  1020 + // name = name.paramCase!;
  1021 + if (!name.startsWith('/')) {
  1022 + name = '/$name';
  1023 + }
  1024 + return Uri.tryParse(name)?.toString() ?? name;
  1025 + }
  1026 +
1001 /// change default config of Get 1027 /// change default config of Get
1002 void config( 1028 void config(
1003 {bool? enableLog, 1029 {bool? enableLog,
@@ -46,10 +46,10 @@ class RouterReportManager<T> { @@ -46,10 +46,10 @@ class RouterReportManager<T> {
46 static void reportRouteDispose(Route disposed) { 46 static void reportRouteDispose(Route disposed) {
47 if (Get.smartManagement != SmartManagement.onlyBuilder) { 47 if (Get.smartManagement != SmartManagement.onlyBuilder) {
48 WidgetsBinding.instance!.addPostFrameCallback((_) { 48 WidgetsBinding.instance!.addPostFrameCallback((_) {
49 - ///TODO: Is necessary this comparator?  
50 - //if (_current != disposed) { 49 + ///TODO: Check if it's necessary to compare _current != disposed
  50 + ///Adding it breaks the context Navigation logic,
  51 + ///as it resolves by Route name.
51 _removeDependencyByRoute(disposed); 52 _removeDependencyByRoute(disposed);
52 - // }  
53 }); 53 });
54 } 54 }
55 } 55 }
1 -import 'dart:async';  
2 -  
3 import 'package:flutter/cupertino.dart'; 1 import 'package:flutter/cupertino.dart';
4 import 'package:flutter/foundation.dart'; 2 import 'package:flutter/foundation.dart';
5 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
@@ -77,6 +77,8 @@ extension GetStringUtils on String { @@ -77,6 +77,8 @@ extension GetStringUtils on String {
77 77
78 String? get camelCase => GetUtils.camelCase(this); 78 String? get camelCase => GetUtils.camelCase(this);
79 79
  80 + String? get paramCase => GetUtils.paramCase(this);
  81 +
80 String numericOnly({bool firstWordOnly = false}) => 82 String numericOnly({bool firstWordOnly = false}) =>
81 GetUtils.numericOnly(this, firstWordOnly: firstWordOnly); 83 GetUtils.numericOnly(this, firstWordOnly: firstWordOnly);
82 84
@@ -551,6 +551,44 @@ class GetUtils { @@ -551,6 +551,44 @@ class GetUtils {
551 return newString[0].toLowerCase() + newString.substring(1); 551 return newString[0].toLowerCase() + newString.substring(1);
552 } 552 }
553 553
  554 + /// credits to "ReCase" package.
  555 + static final RegExp _upperAlphaRegex = RegExp(r'[A-Z]');
  556 + static final _symbolSet = {' ', '.', '/', '_', '\\', '-'};
  557 + static List<String> _groupIntoWords(String text) {
  558 + var sb = StringBuffer();
  559 + var words = <String>[];
  560 + var isAllCaps = text.toUpperCase() == text;
  561 +
  562 + for (var i = 0; i < text.length; i++) {
  563 + var char = text[i];
  564 + var nextChar = i + 1 == text.length ? null : text[i + 1];
  565 + if (_symbolSet.contains(char)) {
  566 + continue;
  567 + }
  568 + sb.write(char);
  569 + var isEndOfWord = nextChar == null ||
  570 + (_upperAlphaRegex.hasMatch(nextChar) && !isAllCaps) ||
  571 + _symbolSet.contains(nextChar);
  572 + if (isEndOfWord) {
  573 + words.add('$sb');
  574 + sb.clear();
  575 + }
  576 + }
  577 + return words;
  578 + }
  579 +
  580 + /// snake_case
  581 + static String? snakeCase(String? text, {String separator = '_'}) {
  582 + if (isNullOrBlank(text)!) {
  583 + return null;
  584 + }
  585 + return _groupIntoWords(text!)
  586 + .map((word) => word.toLowerCase()).join(separator);
  587 + }
  588 +
  589 + /// param-case
  590 + static String? paramCase(String? text) => snakeCase(text, separator: '-');
  591 +
554 /// Extract numeric value of string 592 /// Extract numeric value of string
555 /// Example: OTP 12312 27/04/2020 => 1231227042020ß 593 /// Example: OTP 12312 27/04/2020 => 1231227042020ß
556 /// If firstword only is true, then the example return is "12312" 594 /// If firstword only is true, then the example return is "12312"