khangahs

0.0.0.4

Fixing the en_US from my part to seperate vi_VN , en_US
1 -# Quản lý dependency  
2 -- [Quản lý dependency](#dependency-management) 1 +# Dependency Management
  2 +- [Dependency Management](#dependency-management)
3 - [Instancing methods](#instancing-methods) 3 - [Instancing methods](#instancing-methods)
4 - [Get.put()](#getput) 4 - [Get.put()](#getput)
5 - [Get.lazyPut](#getlazyput) 5 - [Get.lazyPut](#getlazyput)
6 - [Get.putAsync](#getputasync) 6 - [Get.putAsync](#getputasync)
7 - [Get.create](#getcreate) 7 - [Get.create](#getcreate)
8 - - [Sử dụng các phương thức / class](#using-instantiated-methodsclasses)  
9 - - [Khác nhau giữa phương thức (methods)](#differences-between-methods) 8 + - [Using instantiated methods/classes](#using-instantiated-methodsclasses)
  9 + - [Differences between methods](#differences-between-methods)
10 - [Bindings](#bindings) 10 - [Bindings](#bindings)
11 - - [Cách sử dụng](#how-to-use) 11 + - [How to use](#how-to-use)
12 - [BindingsBuilder](#bindingsbuilder) 12 - [BindingsBuilder](#bindingsbuilder)
13 - [SmartManagement](#smartmanagement) 13 - [SmartManagement](#smartmanagement)
14 - - [Cách thay đổi](#How-to-change) 14 + - [How to change](#How-to-change)
15 - [SmartManagement.full](#smartmanagementfull) 15 - [SmartManagement.full](#smartmanagementfull)
16 - [SmartManagement.onlyBuilders](#smartmanagementonlybuilders) 16 - [SmartManagement.onlyBuilders](#smartmanagementonlybuilders)
17 - [SmartManagement.keepFactory](#smartmanagementkeepfactory) 17 - [SmartManagement.keepFactory](#smartmanagementkeepfactory)
18 - - [Cách bindings làm việc ngầm](#how-bindings-work-under-the-hood)  
19 - - [Chí ú](#notes) 18 + - [How bindings work under the hood](#how-bindings-work-under-the-hood)
  19 + - [Notes](#notes)
20 20
21 -Get có một trình quản lý dependency đơn giản và mạnh mẽ cho phép bạn truy xuất cùng một class với Blocs hoặc Controller của bạn chỉ với 1 dòng mã, không có "context", không có InheritedWidget 21 +Get has a simple and powerful dependency manager that allows you to retrieve the same class as your Bloc or Controller with just 1 lines of code, no Provider context, no inheritedWidget:
22 22
23 ```dart 23 ```dart
24 Controller controller = Get.put(Controller()); // Rather Controller controller = Controller(); 24 Controller controller = Get.put(Controller()); // Rather Controller controller = Controller();
25 ``` 25 ```
26 26
27 -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.  
28 -Vì vậy, bạn có thể sử dụng controller (hoặc class Blocs) của mình một cách bình thường 27 +Instead of instantiating your class within the class you are using, you are instantiating it within the Get instance, which will make it available throughout your App.
  28 +So you can use your controller (or Bloc class) normally
29 29
30 -- Note: Nếu bạn đang sử dụng Get's State Manager, hãy chú ý hơn đến [Bindings](#bindings) api, điều này sẽ giúp kết nối chế độ xem với controller của bạn dễ dàng hơn.  
31 -- Note²: Quản lý state của Get được tách biệt khỏi các phần khác của gói, vì vậy, nếu ví dụ: nếu ứng dụng của bạn đã sử dụng trình quản lý state (bất kỳ cái nào, không quan trọng), bạn không cần phải thay đổi điều đó, bạn có thể sử dụng phần dependency này người quản lý không có vấn đề gì cả 30 +- Note: If you are using Get's State Manager, pay more attention to the [Bindings](#bindings) api, which will make easier to connect your view to your controller.
  31 +- Note²: Get dependency management is decloupled from other parts of the package, so if for example your app is already using a state manager (any one, it doesn't matter), you don't need to change that, you can use this dependency injection manager with no problems at all
32 32
33 ## Instancing methods 33 ## Instancing methods
34 -Các phương thức và các tham số có thể định cấu hình của nó là: 34 +The methods and it's configurable parameters are:
35 35
36 ### Get.put() 36 ### Get.put()
37 37
38 -Cách phổ biến nhất để chèn một dependency, là một điều tốt cho controller của View của bạn. 38 +The most common way of inserting a dependency. Good for the controllers of your views for example.
39 39
40 ```dart 40 ```dart
41 Get.put<SomeClass>(SomeClass()); 41 Get.put<SomeClass>(SomeClass());
@@ -43,7 +43,7 @@ Get.put<LoginController>(LoginController(), permanent: true); @@ -43,7 +43,7 @@ Get.put<LoginController>(LoginController(), permanent: true);
43 Get.put<ListItemController>(ListItemController, tag: "some unique string"); 43 Get.put<ListItemController>(ListItemController, tag: "some unique string");
44 ``` 44 ```
45 45
46 -Đây là tùy chọn mà bạn có thể đặt lệnh: 46 +This is all options you can set when using put:
47 ```dart 47 ```dart
48 Get.put<S>( 48 Get.put<S>(
49 // mandatory: the class that you want to get to save, like a controller or anything 49 // mandatory: the class that you want to get to save, like a controller or anything
@@ -74,7 +74,7 @@ Get.put<S>( @@ -74,7 +74,7 @@ Get.put<S>(
74 ``` 74 ```
75 75
76 ### Get.lazyPut 76 ### Get.lazyPut
77 -Có thể lazyLoad một dependecy để nó chỉ được khởi tạo khi được sử dụng. Rất hữu ích cho các class ngốn nhiều tài nguyên hoặc nếu bạn muốn khởi tạo một số class chỉ ở một nơi (như trong class Bindings) và bạn biết rằng mình sẽ không sử dụng class đó tại thời điểm nhất định. 77 +It is possible to lazyLoad a dependency so that it will be instantiated only when is used. Very useful for computational expensive classes or if you want to instantiate several classes in just one place (like in a Bindings class) and you know you will not gonna use that class at that time.
78 78
79 ```dart 79 ```dart
80 /// ApiMock will only be called when someone uses Get.find<ApiMock> for the first time 80 /// ApiMock will only be called when someone uses Get.find<ApiMock> for the first time
@@ -92,7 +92,7 @@ Get.lazyPut<FirebaseAuth>( @@ -92,7 +92,7 @@ Get.lazyPut<FirebaseAuth>(
92 Get.lazyPut<Controller>( () => Controller() ) 92 Get.lazyPut<Controller>( () => Controller() )
93 ``` 93 ```
94 94
95 -Đây là các tùy chọn bạn có thể đặt lệnh: 95 +This is all options you can set when using lazyPut:
96 ```dart 96 ```dart
97 Get.lazyPut<S>( 97 Get.lazyPut<S>(
98 // mandatory: a method that will be executed when your class is called for the first time 98 // mandatory: a method that will be executed when your class is called for the first time
@@ -112,7 +112,7 @@ Get.lazyPut<S>( @@ -112,7 +112,7 @@ Get.lazyPut<S>(
112 ``` 112 ```
113 113
114 ### Get.putAsync 114 ### Get.putAsync
115 - Đây là khi bạn muốn xài asynchronize code `Get.putAsync`: 115 +If you want to register an asynchronous instance, you can use `Get.putAsync`:
116 116
117 ```dart 117 ```dart
118 Get.putAsync<SharedPreferences>(() async { 118 Get.putAsync<SharedPreferences>(() async {
@@ -124,7 +124,7 @@ Get.putAsync<SharedPreferences>(() async { @@ -124,7 +124,7 @@ Get.putAsync<SharedPreferences>(() async {
124 Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() ) 124 Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() )
125 ``` 125 ```
126 126
127 -Đây là tùy chọn bạn có thể đặt lệnh với putAsync: 127 +This is all options you can set when using putAsync:
128 ```dart 128 ```dart
129 Get.putAsync<S>( 129 Get.putAsync<S>(
130 130
@@ -143,14 +143,14 @@ Get.putAsync<S>( @@ -143,14 +143,14 @@ Get.putAsync<S>(
143 143
144 ### Get.create 144 ### Get.create
145 145
146 -Cái này hơi khó giải thích, nhưng sự khác nhau giữa chúng có thể được tìm thấy trên mục [Differences between methods:](#differences-between-methods) 146 +This one is tricky. A detailed explanation of what this is and the differences between the other one can be found on [Differences between methods:](#differences-between-methods) section
147 147
148 ```dart 148 ```dart
149 Get.Create<SomeClass>(() => SomeClass()); 149 Get.Create<SomeClass>(() => SomeClass());
150 Get.Create<LoginController>(() => LoginController()); 150 Get.Create<LoginController>(() => LoginController());
151 ``` 151 ```
152 152
153 -Tùy chọn có thể sử dụng: 153 +This is all options you can set when using create:
154 154
155 ```dart 155 ```dart
156 Get.create<S>( 156 Get.create<S>(
@@ -171,9 +171,9 @@ Get.create<S>( @@ -171,9 +171,9 @@ Get.create<S>(
171 bool permanent = true 171 bool permanent = true
172 ``` 172 ```
173 173
174 -## Sử dụng các phương thức / class 174 +## Using instantiated methods/classes
175 175
176 -Hãy tưởng tượng rằng bạn đã điều hướng qua nhiều route và bạn cần một dữ liệu còn sót trong controller của mình, bạn sẽ cần một trình quản lý state kết hợp với Provider hoặc Get_it, phải hem? Với Get, bạn chỉ cần yêu cầu Get to "find" cho controller của mình và thế là xong: 176 +Imagine that you have navigated through numerous routes, and you need a data that was left behind in your controller, you would need a state manager combined with the Provider or Get_it, correct? Not with Get. You just need to ask Get to "find" for your controller, you don't need any additional dependencies:
177 177
178 ```dart 178 ```dart
179 final controller = Get.find<Controller>(); 179 final controller = Get.find<Controller>();
@@ -184,64 +184,64 @@ Controller controller = Get.find(); @@ -184,64 +184,64 @@ Controller controller = Get.find();
184 // You can have 1 million controllers instantiated, Get will always give you the right controller. 184 // You can have 1 million controllers instantiated, Get will always give you the right controller.
185 ``` 185 ```
186 186
187 -Và sau đó, bạn sẽ có thể khôi phục dữ liệu controller của mình đã lấy được ở đó: 187 +And then you will be able to recover your controller data that was obtained back there:
188 188
189 ```dart 189 ```dart
190 Text(controller.textFromApi); 190 Text(controller.textFromApi);
191 ``` 191 ```
192 192
193 -Vì giá trị trả về là một class bình thường, bạn có thể làm bất cứ điều gì bạn muốn: 193 +Since the returned value is a normal class, you can do anything you want:
194 ```dart 194 ```dart
195 int count = Get.find<SharedPreferences>().getInt('counter'); 195 int count = Get.find<SharedPreferences>().getInt('counter');
196 print(count); // out: 12345 196 print(count); // out: 12345
197 ``` 197 ```
198 198
199 -Để xóa một controller đang chạy ngầm của Get: 199 +To remove an instance of Get:
200 200
201 ```dart 201 ```dart
202 -Get.delete<Controller>(); //thường thì Get tự xóa, bạn không cần phải đặt lệnh này. 202 +Get.delete<Controller>(); //usually you don't need to do this because GetX already delete unused controllers
203 ``` 203 ```
204 204
205 -## Khác nhau giữa phương thức (methods) 205 +## Differences between methods
206 206
207 -Đầu tiên, hãy nói về `fenix` của Get.lazyPut và `permanent`của các phương thức khác. 207 +First, let's of the `fenix` of Get.lazyPut and the `permanent` of the other methods.
208 208
209 -Sự khác biệt cơ bản giữa `permanent` và `fenix` là cách bạn muốn lưu trữ các cá thể của mình. 209 +The fundamental difference between `permanent` and `fenix` is how you want to store your instances.
210 210
211 -Củng cố: theo mặc định, GetX xóa các trường hợp khi chúng không được sử dụng.  
212 -Có nghĩa là: Nếu màn hình 1 có controller 1 và màn hình 2 có controller 2 và bạn xóa route đầu tiên khỏi stack, (chẳng hạn như nếu bạn sử dụng `` Get.off () 'hoặc' `Get.offNamed()``) thì controller 1 bị mất việc sử dụng nó vì vậy nó sẽ bị xóa. 211 +Reinforcing: by default, GetX deletes instances when they are not in use.
  212 +It means that: If screen 1 has controller 1 and screen 2 has controller 2 and you remove the first route from stack, (like if you use `Get.off()` or `Get.offNamed()`) the controller 1 lost its use so it will be erased.
213 213
214 -Nhưng nếu bạn muốn chọn sử dụng `permanent: true`, thì controller sẽ không bị mất trong quá trình chuyển đổi này - điều này rất hữu ích cho các dịch vụ mà bạn muốn duy trì hoạt động trong toàn bộ ứng dụng. 214 +But if you want to opt for using `permanent:true`, then the controller will not be lost in this transition - which is very useful for services that you want to keep alive throughout the entire application.
215 215
216 -Mặt khác, `fenix` dành cho các dịch vụ mà bạn không lo bị mất giữa các lần thay đổi màn hình, nhưng khi bạn cần dịch vụ đó, bạn hy vọng rằng nó vẫn tồn tại. Vì vậy, về cơ bản, nó sẽ loại bỏ controller / service / class không sử dụng, nhưng khi bạn cần, nó sẽ "tạo lại từ đống tro tàn" ở một trường hợp (instance) mới. 216 +`fenix` in the other hand is for services that you don't worry in losing between screen changes, but when you need that service, you expect that it is alive. So basically, it will dispose the unused controller/service/class, but when you need it, it will "recreate from the ashes" a new instance.
217 217
218 -Tiếp tục với sự khác biệt giữa các phương pháp: 218 +Proceeding with the differences between methods:
219 219
220 -- Get.put và Get.putAsync tuân theo cùng một thứ tự tạo, với sự khác biệt là một cái sử dụng phương thức không đồng bộ: hai phương thức đó đều tạo và khởi tạo các trường hợp. Cái sử dụng không đồng bộ được chèn trực tiếp vào bộ nhớ, bằng cách sử dụng phương thức nội bộ `insert` với các tham số `permanent: false` và` isSingleton: true` (tham số isSingleton này chỉ nhằm mục đích cho biết liệu nó có sử dụng dependency vào `dependency` hay không hoặc nếu nó được sử dụng dependency vào `FcBuilderFunc`). Sau đó, `Get.find ()` được gọi để khởi tạo ngay lập tức các các trường hợp trên bộ nhớ. 220 +- Get.put and Get.putAsync follows the same creation order, with the difference that the second uses an asynchronous method: those two methods creates and initializes the instance. That one is inserted directly in the memory, using the internal method `insert` with the parameters `permanent: false` and `isSingleton: true` (this isSingleton parameter only purpose is to tell if it is to use the dependency on `dependency` or if it is to use the dependency on `FcBuilderFunc`). After that, `Get.find()` is called that immediately initialize the instances that are on memory.
221 221
222 -- Get.create: Như tên của nó, nó sẽ "tạo ra" sự dependency cho bạn! Tương tự như `Get.put ()`, nó cũng gọi phương thức nội bộ là `insert` để các trường hợp. Nhưng `permanent` trở thành true và` isSingleton` trở thành false (vì chúng ta đang "tạo" dependency của mình, không có cách nào để nó là một instace singleton, đó là lý do tại sao lại là false). Và bởi vì nó có `permanent: true`, chúng tôi mặc định có lợi ích là không bị mất nó giữa các màn hình! Ngoài ra, `` Get.find () 'không được gọi ngay lập tức, nó phải chờ được sử dụng trong màn hình để được gọi. Nó được tạo ra theo cách này để sử dụng tham số `permanent ', vì vậy, đáng chú ý là` Get.create () `được tạo ra với mục tiêu tạo ra các phiên bản không được chia sẻ, nhưng không bị loại bỏ, như ví dụ: trong listView, mà bạn muốn có một phiên bản duy nhất cho danh sách đó - do đó, Get.create phải được sử dụng cùng với GetWidget. 222 +- Get.create: As the name implies, it will "create" your dependency! Similar to `Get.put()`, it also calls the internal method `insert` to instancing. But `permanent` became true and `isSingleton` became false (since we are "creating" our dependency, there is no way for it to be a singleton instace, that's why is false). And because it has `permanent: true`, we have by default the benefit of not losing it between screens! Also, `Get.find()` is not called immediately, it wait to be used in the screen to be called. It is created this way to make use of the parameter `permanent`, since then, worth noticing, `Get.create()` was made with the goal of create not shared instances, but don't get disposed, like for example a button in a listView, that you want a unique instance for that list - because of that, Get.create must be used together with GetWidget.
223 223
224 -- Get.lazyPut: Như tên của nó, nó là một quy trình lười biếng. Cá thể được tạo, nhưng nó không được gọi để sử dụng ngay lập tức, nó vẫn đang chờ được gọi. Trái ngược với các phương thức khác, `insert` không được gọi ở đây. Thay vào đó, cá thể được chèn vào một phần khác của bộ nhớ, một phần chịu trách nhiệm cho biết liệu cá thể đó có thể được tạo lại hay không, chúng ta hãy gọi nó là "nhà máy". Nếu chúng ta muốn tạo ra thứ gì đó để sử dụng sau này, nó sẽ không bị trộn lẫn với những thứ đã được sử dụng ngay bây giờ. Và đây là nơi phép thuật của `fenix` đi vào: nếu bạn chọn bỏ` fenix: false`, và `smartManagement` của bạn không phải là` keepFactory`, thì khi sử dụng `Get.find`, instance sẽ thay đổi vị trí trong bộ nhớ từ "nhà máy" đến vùng bộ nhớ cá thể chung. Ngay sau đó, theo mặc định, nó được xóa khỏi "nhà máy". Bây giờ, nếu bạn chọn `fenix: true`, cá thể vẫn tiếp tục tồn tại trong phần dành riêng này, thậm chí sẽ chuyển sang vùng chung, sẽ được gọi lại trong tương lai. 224 +- Get.lazyPut: As the name implies, it is a lazy proccess. The instance is create, but it is not called to be used immediately, it remains waiting to be called. Contrary to the other methods, `insert` is not called here. Instead, the instance is inserted in another part of the memory, a part responsible to tell if the instance can be recreated or not, let's call it "factory". If we want to create something to be used later, it will not be mix with things been used right now. And here is where `fenix` magic enters: if you opt to leaving `fenix: false`, and your `smartManagement` are not `keepFactory`, then when using `Get.find` the instance will change the place in the memory from the "factory" to common instance memory area. Right after that, by default it is removed from the "factory". Now, if you opt for `fenix: true`, the instance continues to exist in this dedicated part, even going to the common area, to be called again in the future.
225 225
226 ## Bindings 226 ## Bindings
227 227
228 -Có lẽ, một trong những điểm khác biệt lớn của gói này là khả năng tích hợp đầy đủ các route, trình quản lý state và trình quản lý dependency.  
229 -Khi một route bị xóa khỏi stack, tất cả các controller, biến và phiên bản của các đối tượng liên quan đến nó sẽ bị xóa khỏi bộ nhớ. Nếu bạn đang sử dụng luồng hoặc bộ hẹn giờ, chúng sẽ tự động bị đóng và bạn không phải lo lắng về bất kỳ điều gì trong số đó.  
230 -Trong phiên bản 2.10 Được triển khai hoàn toàn API bindings.  
231 -Bây giờ bạn không cần sử dụng phương thức init nữa. Bạn thậm chí không cần phải nhập controller của mình nếu bạn không muốn. Bạn có thể khởi động controller và dịch vụ của mình ở nơi thích hợp cho việc đó.  
232 -Lớp Binding là một class sẽ tách riêng việc tiêm dependency, trong khi "bindings" các route đường tới trình quản lý state và trình quản lý dependency.  
233 -Điều này cho phép Nhận biết màn hình nào đang được hiển thị khi một controller cụ thể được sử dụng và biết vị trí và cách vứt bỏ nó.  
234 -Ngoài ra, class Binding sẽ cho phép bạn kiểm soát cấu hình SmartManager. Bạn có thể định cấu hình các phần dependency được sắp xếp khi xóa một route khỏi ngăn xếp hoặc khi widget con đã sử dụng nó được bố trí hoặc không. Bạn sẽ có quản lý dependency thông minh làm việc cho bạn, nhưng ngay cả như vậy, bạn có thể định cấu hình nó theo ý muốn. 228 +One of the great differentials of this package, perhaps, is the possibility of full integration of the routes, state manager and dependency manager.
  229 +When a route is removed from the Stack, all controllers, variables, and instances of objects related to it are removed from memory. If you are using streams or timers, they will be closed automatically, and you don't have to worry about any of that.
  230 +In version 2.10 Get completely implemented the Bindings API.
  231 +Now you no longer need to use the init method. You don't even have to type your controllers if you don't want to. You can start your controllers and services in the appropriate place for that.
  232 +The Binding class is a class that will decouple dependency injection, while "binding" routes to the state manager and dependency manager.
  233 +This allows Get to know which screen is being displayed when a particular controller is used and to know where and how to dispose of it.
  234 +In addition, the Binding class will allow you to have SmartManager configuration control. You can configure the dependencies to be arranged when removing a route from the stack, or when the widget that used it is laid out, or neither. You will have intelligent dependency management working for you, but even so, you can configure it as you wish.
235 235
236 ### Bindings class 236 ### Bindings class
237 237
238 -- Tạo một class và implements Binding 238 +- Create a class and implements Binding
239 239
240 ```dart 240 ```dart
241 class HomeBinding implements Bindings {} 241 class HomeBinding implements Bindings {}
242 ``` 242 ```
243 243
244 -IDE của bạn sẽ tự động yêu cầu bạn ghi đè phương thức "dependency" và bạn chỉ cần nhấp vào đèn, ghi đè phương thức và chèn tất cả các class bạn sẽ sử dụng trên route đó: 244 +Your IDE will automatically ask you to override the "dependencies" method, and you just need to click on the lamp, override the method, and insert all the classes you are going to use on that route:
245 245
246 ```dart 246 ```dart
247 class HomeBinding implements Bindings { 247 class HomeBinding implements Bindings {
@@ -260,9 +260,9 @@ class DetailsBinding implements Bindings { @@ -260,9 +260,9 @@ class DetailsBinding implements Bindings {
260 } 260 }
261 ``` 261 ```
262 262
263 -Bây giờ bạn chỉ cần thông báo route của mình, rằng bạn sẽ sử dụng bindings đó để tạo kết nối giữa trình quản lý route, các dependency và state. 263 +Now you just need to inform your route, that you will use that binding to make the connection between route manager, dependencies and states.
264 264
265 -- Sử dụng routes có tên: 265 +- Using named routes:
266 266
267 ```dart 267 ```dart
268 getPages: [ 268 getPages: [
@@ -279,16 +279,16 @@ getPages: [ @@ -279,16 +279,16 @@ getPages: [
279 ]; 279 ];
280 ``` 280 ```
281 281
282 -- Sử dụng routes thường: 282 +- Using normal routes:
283 283
284 ```dart 284 ```dart
285 Get.to(Home(), binding: HomeBinding()); 285 Get.to(Home(), binding: HomeBinding());
286 Get.to(DetailsView(), binding: DetailsBinding()) 286 Get.to(DetailsView(), binding: DetailsBinding())
287 ``` 287 ```
288 288
289 -Ở đó, bạn không phải lo lắng về việc quản lý bộ nhớ của ứng dụng của mình nữa, Get sẽ thay bạn làm điều đó. 289 +There, you don't have to worry about memory management of your application anymore, Get will do it for you.
290 290
291 -Lớp Binding được gọi khi một route được gọi, bạn có thể tạo một "InitialBinding trong GetMaterialApp của mình để chèn tất cả các dependency sẽ được tạo. 291 +The Binding class is called when a route is called, you can create an "initialBinding in your GetMaterialApp to insert all the dependencies that will be created.
292 292
293 ```dart 293 ```dart
294 GetMaterialApp( 294 GetMaterialApp(
@@ -299,8 +299,8 @@ GetMaterialApp( @@ -299,8 +299,8 @@ GetMaterialApp(
299 299
300 ### BindingsBuilder 300 ### BindingsBuilder
301 301
302 -Cách mặc định để tạo bindings là tạo một class thực hiện các bindings.  
303 -Nhưng cách khác, bạn có thể sử dụng lệnh gọi lại `BindingsBuilder` để bạn có thể chỉ cần sử dụng một hàm để khởi tạo bất cứ thứ gì bạn muốn. 302 +The default way of creating a binding is by creating a class that implements Bindings.
  303 +But alternatively, you can use `BindingsBuilder` callback so that you can simply use a function to instantiate whatever you desire.
304 304
305 Example: 305 Example:
306 306
@@ -324,19 +324,19 @@ getPages: [ @@ -324,19 +324,19 @@ getPages: [
324 ]; 324 ];
325 ``` 325 ```
326 326
327 -Bằng cách đó, bạn có thể tránh tạo một class Binding cho mỗi routes, làm cho việc này trở nên đơn giản hơn. 327 +That way you can avoid to create one Binding class for each route making this even simpler.
328 328
329 -Cả hai cách làm việc đều hoàn toàn tốt và chúng tôi muốn bạn sử dụng những gì phù hợp với sở thích của bạn nhất. 329 +Both ways of doing work perfectly fine and we want you to use what most suit your tastes.
330 330
331 ### SmartManagement 331 ### SmartManagement
332 332
333 -GetX theo mặc định loại bỏ controller không sử dụng khỏi bộ nhớ, ngay cả khi xảy ra lỗi và widget con sử dụng nó không được xử lý đúng cách.  
334 -Đây được gọi là chế độ quản lý dependency `` đầy đủ`.  
335 -Nhưng nếu bạn muốn thay đổi cách GetX kiểm soát việc xử lý các class, bạn có class `SmartManagement` để bạn có thể thiết lập các hành vi khác nhau. 333 +GetX by default disposes unused controllers from memory, even if a failure occurs and a widget that uses it is not properly disposed.
  334 +This is what is called the `full` mode of dependency management.
  335 +But if you want to change the way GetX controls the disposal of classes, you have `SmartManagement` class that you can set different behaviors.
336 336
337 -#### Cách thay đổi 337 +#### How to change
338 338
339 -Nếu bạn muốn thay đổi cấu hình này (mà bạn thường không cần) thì đây là cách: 339 +If you want to change this config (which you usually don't need) this is the way:
340 340
341 ```dart 341 ```dart
342 void main () { 342 void main () {
@@ -351,30 +351,30 @@ void main () { @@ -351,30 +351,30 @@ void main () {
351 351
352 #### SmartManagement.full 352 #### SmartManagement.full
353 353
354 -Nó là một trong những mặc định. Loại bỏ các class không được sử dụng và không được đặt thành vĩnh viễn. Trong phần lớn các trường hợp, bạn sẽ muốn giữ nguyên cấu hình này. Nếu bạn mới sử dụng GetX thì đừng thay đổi điều này. 354 +It is the default one. Dispose classes that are not being used and were not set to be permanent. In the majority of the cases you will want to keep this config untouched. If you new to GetX then don't change this.
355 355
356 #### SmartManagement.onlyBuilders 356 #### SmartManagement.onlyBuilders
357 -Với tùy chọn này, chỉ những controller bắt đầu trong `init: 'hoặc được tải vào Binding với` `Get.lazyPut ()` mới được xử lý. 357 +With this option, only controllers started in `init:` or loaded into a Binding with `Get.lazyPut()` will be disposed.
358 358
359 -Nếu bạn sử dụng `Get.put () 'hoặc' Get.putAsync ()` hoặc bất kỳ cách tiếp cận nào khác, SmartManagement sẽ không có quyền loại trừ sự dependency này. 359 +If you use `Get.put()` or `Get.putAsync()` or any other approach, SmartManagement will not have permissions to exclude this dependency.
360 360
361 -Với hành vi mặc định, ngay cả các widget con được khởi tạo bằng "Get.put" sẽ bị xóa, không giống như SmartManagement.onlyBuilders. 361 +With the default behavior, even widgets instantiated with "Get.put" will be removed, unlike SmartManagement.onlyBuilders.
362 362
363 #### SmartManagement.keepFactory 363 #### SmartManagement.keepFactory
364 364
365 -Cũng giống như SmartManagement.full, nó sẽ loại bỏ các phần dependency của nó khi nó không được sử dụng nữa. Tuy nhiên, nó sẽ giữ nguyên chế độ factory của họ, có nghĩa là nó sẽ tạo lại phần dependency nếu bạn cần lại phiên bản đó. 365 +Just like SmartManagement.full, it will remove it's dependencies when it's not being used anymore. However, it will keep their factory, which means it will recreate the dependency if you need that instance again.
366 366
367 -### Cách bindings làm việc ngầm  
368 -Các liên kết tạo ra các factory tạm thời, được tạo ra ngay khi bạn nhấp để chuyển sang màn hình khác và sẽ bị phá hủy ngay sau khi hoạt ảnh thay đổi màn hình xảy ra.  
369 -Điều này xảy ra quá nhanh đến nỗi máy phân tích thậm chí sẽ không thể đăng ký nó.  
370 -Khi bạn điều hướng đến màn hình này một lần nữa, một factory tạm thời mới sẽ được gọi, vì vậy điều này thích hợp hơn khi sử dụng SmartManagement.keepFactory, nhưng nếu bạn không muốn tạo Bindings hoặc muốn giữ tất cả các dependency của mình trên cùng một Binding, thì chắc chắn sẽ giúp ích cho bạn.  
371 -Các factory chiếm ít bộ nhớ, chúng không chứa các cá thể mà là một chức năng có "hình dạng" của class đó mà bạn muốn.  
372 -Điều này có chi phí bộ nhớ rất thấp, nhưng vì mục đích của lib này là để đạt được hiệu suất tối đa có thể bằng cách sử dụng tài nguyên tối thiểu, Get xóa ngay cả các factory theo mặc định.  
373 -Sử dụng cái nào thuận tiện nhất cho bạn. 367 +### How bindings work under the hood
  368 +Bindings creates transitory factories, which are created the moment you click to go to another screen, and will be destroyed as soon as the screen-changing animation happens.
  369 +This happens so fast that the analyzer will not even be able to register it.
  370 +When you navigate to this screen again, a new temporary factory will be called, so this is preferable to using SmartManagement.keepFactory, but if you don't want to create Bindings, or want to keep all your dependencies on the same Binding, it will certainly help you.
  371 +Factories take up little memory, they don't hold instances, but a function with the "shape" of that class you want.
  372 +This has a very low cost in memory, but since the purpose of this lib is to get the maximum performance possible using the minimum resources, Get removes even the factories by default.
  373 +Use whichever is most convenient for you.
374 374
375 -## Chí ú 375 +## Notes
376 376
377 -- KHÔNG SỬ DỤNG SmartManagement.keepFactory nếu bạn đang sử dụng nhiều Binding. Nó được thiết kế để sử dụng mà không có Bindings, hoặc với một Bindings duy nhất được liên kết trong `initialBinding` của GetMaterialApp. 377 +- DO NOT USE SmartManagement.keepFactory if you are using multiple Bindings. It was designed to be used without Bindings, or with a single Binding linked in the GetMaterialApp's initialBinding.
378 378
379 -- Việc sử dụng Bindings là hoàn toàn tùy chọn, nếu muốn, bạn có thể sử dụng `Get.put () 'và' Get.find()` trên các class sử dụng controller nhất định mà không gặp bất kỳ vấn đề gì.  
380 -Tuy nhiên, nếu bạn làm việc với Service hoặc bất kỳ abstract nào khác, tôi khuyên bạn nên sử dụng Bindings để tổ chức tốt hơn. 379 +- Using Bindings is completely optional, if you want you can use `Get.put()` and `Get.find()` on classes that use a given controller without any problem.
  380 +However, if you work with Services or any other abstraction, I recommend using Bindings for a better organization.
1 -- [Quản lý route](#route-management)  
2 - - [Hướng dẫn sử dụng trước khi dùng](#how-to-use)  
3 - - [Điều hướng không cần tên](#navigation-without-named-routes)  
4 - - [Điều hướng cần tên](#navigation-with-named-routes)  
5 - - [Gửi data cho route có tên](#send-data-to-named-routes) 1 +- [Route Management](#route-management)
  2 + - [How to use](#how-to-use)
  3 + - [Navigation without named routes](#navigation-without-named-routes)
  4 + - [Navigation with named routes](#navigation-with-named-routes)
  5 + - [Send data to named Routes](#send-data-to-named-routes)
6 - [Dynamic urls links](#dynamic-urls-links) 6 - [Dynamic urls links](#dynamic-urls-links)
7 - [Middleware](#middleware) 7 - [Middleware](#middleware)
8 - - [Điều hướng không cần context](#navigation-without-context) 8 + - [Navigation without context](#navigation-without-context)
9 - [SnackBars](#snackbars) 9 - [SnackBars](#snackbars)
10 - [Dialogs](#dialogs) 10 - [Dialogs](#dialogs)
11 - [BottomSheets](#bottomsheets) 11 - [BottomSheets](#bottomsheets)
12 - - [Điều hướng lồng (Nested Navigation)](#nested-navigation) 12 + - [Nested Navigation](#nested-navigation)
13 13
14 -# Quản lý route 14 +# Route Management
15 15
16 -Đây là lời giải thích đầy đủ về tất cả những gì có cho Getx khi vấn đề là quản lý routes. 16 +This is the complete explanation of all there is to Getx when the matter is route management.
17 17
18 -## Hướng dẫn sử dụng trước khi dùng 18 +## How to use
19 19
20 -Thêm cái này vào file pubspec.yaml của bạn: 20 +Add this to your pubspec.yaml file:
21 21
22 ```yaml 22 ```yaml
23 dependencies: 23 dependencies:
24 get: 24 get:
25 ``` 25 ```
26 26
27 -Nếu bạn định sử dụng các routes / snackbars / dialogs / bottomsheets mà không có "context" hoặc sử dụng các API cấp cao, bạn chỉ cần thêm Get trước MaterialApp của mình, biến nó thành GetMaterialApp và tung hành! 27 +If you are going to use routes/snackbars/dialogs/bottomsheets without context, or use the high-level Get APIs, you need to simply add "Get" before your MaterialApp, turning it into GetMaterialApp and enjoy!
28 28
29 ```dart 29 ```dart
30 GetMaterialApp( // Before: MaterialApp( 30 GetMaterialApp( // Before: MaterialApp(
@@ -32,39 +32,39 @@ GetMaterialApp( // Before: MaterialApp( @@ -32,39 +32,39 @@ GetMaterialApp( // Before: MaterialApp(
32 ) 32 )
33 ``` 33 ```
34 34
35 -## Điều hướng không cần tên 35 +## Navigation without named routes
36 36
37 -Để điều hướng đến một màn hình mới: 37 +To navigate to a new screen:
38 38
39 ```dart 39 ```dart
40 Get.to(NextScreen()); 40 Get.to(NextScreen());
41 ``` 41 ```
42 42
43 -Để đóng snackbars, dialog, bottomsheets hoặc bất cứ thứ gì bạn thường đóng bằng Navigator.pop (context); 43 +To close snackbars, dialogs, bottomsheets, or anything you would normally close with Navigator.pop(context);
44 44
45 ```dart 45 ```dart
46 Get.back(); 46 Get.back();
47 ``` 47 ```
48 48
49 -Để chuyển đến màn hình tiếp theo và không có tùy chọn nào để quay lại màn hình trước đó (để sử dụng trong SplashScreens, màn hình đăng nhập, v.v.) 49 +To go to the next screen and no option to go back to the previous screen (for use in SplashScreens, login screens and etc.)
50 50
51 ```dart 51 ```dart
52 Get.off(NextScreen()); 52 Get.off(NextScreen());
53 ``` 53 ```
54 54
55 -Để chuyển đến màn hình tiếp theo và hủy tất cả các lộ trình trước đó (hữu ích trong giỏ hàng, polls và test) 55 +To go to the next screen and cancel all previous routes (useful in shopping carts, polls, and tests)
56 56
57 ```dart 57 ```dart
58 Get.offAll(NextScreen()); 58 Get.offAll(NextScreen());
59 ``` 59 ```
60 60
61 -Để điều hướng đến routes tiếp theo và nhận hoặc cập nhật dữ liệu ngay sau khi bạn trở về từ routes đó: 61 +To navigate to the next route, and receive or update data as soon as you return from it:
62 62
63 ```dart 63 ```dart
64 var data = await Get.to(Payment()); 64 var data = await Get.to(Payment());
65 ``` 65 ```
66 66
67 -trên màn hình khác, gửi dữ liệu cho routes trước đó: 67 +on other screen, send a data for previous route:
68 68
69 ```dart 69 ```dart
70 Get.back(result: 'success'); 70 Get.back(result: 'success');
@@ -78,9 +78,9 @@ ex: @@ -78,9 +78,9 @@ ex:
78 if(data == 'success') madeAnything(); 78 if(data == 'success') madeAnything();
79 ``` 79 ```
80 80
81 -Bạn không muốn học cú pháp của chúng tôi?  
82 -Chỉ cần thay đổi Navigator (chữ in hoa) thành navigator (chữ thường) và bạn sẽ có tất cả các chức năng của điều hướng tiêu chuẩn mà không cần phải sử dụng "context"  
83 -Thí dụ: 81 +Don't you want to learn our syntax?
  82 +Just change the Navigator (uppercase) to navigator (lowercase), and you will have all the functions of the standard navigation, without having to use context
  83 +Example:
84 84
85 ```dart 85 ```dart
86 86
@@ -109,9 +109,9 @@ Get.to(HomePage()); @@ -109,9 +109,9 @@ Get.to(HomePage());
109 109
110 ``` 110 ```
111 111
112 -## Điều hướng cần tên 112 +## Navigation with named routes
113 113
114 -- Nếu bạn thích điều hướng bằng tên, Get cũng hỗ trợ điều này. 114 +- If you prefer to navigate by namedRoutes, Get also supports this.
115 115
116 To navigate to nextScreen 116 To navigate to nextScreen
117 117
@@ -119,19 +119,19 @@ To navigate to nextScreen @@ -119,19 +119,19 @@ To navigate to nextScreen
119 Get.toNamed("/NextScreen"); 119 Get.toNamed("/NextScreen");
120 ``` 120 ```
121 121
122 -Để điều hướng và xóa màn hình trước đó khỏi cây widget. 122 +To navigate and remove the previous screen from the tree.
123 123
124 ```dart 124 ```dart
125 Get.offNamed("/NextScreen"); 125 Get.offNamed("/NextScreen");
126 ``` 126 ```
127 127
128 -Để điều hướng và xóa tất cả các màn hình trước đó khỏi cây widget. 128 +To navigate and remove all previous screens from the tree.
129 129
130 ```dart 130 ```dart
131 Get.offAllNamed("/NextScreen"); 131 Get.offAllNamed("/NextScreen");
132 ``` 132 ```
133 133
134 -Để định dạng routes, sử dụng GetMaterialApp: 134 +To define routes, use GetMaterialApp:
135 135
136 ```dart 136 ```dart
137 void main() { 137 void main() {
@@ -152,7 +152,7 @@ void main() { @@ -152,7 +152,7 @@ void main() {
152 } 152 }
153 ``` 153 ```
154 154
155 -Để xử lý điều hướng đến các routes không được xác định (lỗi 404), bạn có thể xác định trang 'không xác định' trong GetMaterialApp. 155 +To handle navigation to non-defined routes (404 error), you can define an unknownRoute page in GetMaterialApp.
156 156
157 ```dart 157 ```dart
158 void main() { 158 void main() {
@@ -169,15 +169,15 @@ void main() { @@ -169,15 +169,15 @@ void main() {
169 } 169 }
170 ``` 170 ```
171 171
172 -### Gửi data cho route có tên 172 +### Send data to named Routes
173 173
174 -Chỉ cần gửi những gì bạn muốn cho các đối số (arguments). Get chấp nhận bất kỳ thứ gì ở đây, cho dù đó là String, Map, List hay thậm chí là một class trường hợp. 174 +Just send what you want for arguments. Get accepts anything here, whether it is a String, a Map, a List, or even a class instance.
175 175
176 ```dart 176 ```dart
177 Get.toNamed("/NextScreen", arguments: 'Get is the best'); 177 Get.toNamed("/NextScreen", arguments: 'Get is the best');
178 ``` 178 ```
179 179
180 -Trong class controller của bạn: 180 +on your class or controller:
181 181
182 ```dart 182 ```dart
183 print(Get.arguments); 183 print(Get.arguments);
@@ -186,13 +186,13 @@ print(Get.arguments); @@ -186,13 +186,13 @@ print(Get.arguments);
186 186
187 ### Dynamic urls links 187 ### Dynamic urls links
188 188
189 -Get hỗ trợ các url động nâng cao giống như trên Web. Các nhà phát triển web có lẽ đã muốn tính năng này trên Flutter và rất có thể đã thấy một gói hứa hẹn tính năng này và cung cấp một cú pháp hoàn toàn khác so với một URL sẽ có trên web, và Get cũng giải quyết được điều này. 189 +Get offer advanced dynamic urls just like on the Web. Web developers have probably already wanted this feature on Flutter, and most likely have seen a package promise this feature and deliver a totally different syntax than a URL would have on web, but Get also solves that.
190 190
191 ```dart 191 ```dart
192 Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo"); 192 Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo");
193 ``` 193 ```
194 194
195 -trong controller/bloc/stateful/stateless của class: 195 +on your controller/bloc/stateful/stateless class:
196 196
197 ```dart 197 ```dart
198 print(Get.parameters['id']); 198 print(Get.parameters['id']);
@@ -201,7 +201,7 @@ print(Get.parameters['name']); @@ -201,7 +201,7 @@ print(Get.parameters['name']);
201 // out: Enzo 201 // out: Enzo
202 ``` 202 ```
203 203
204 -Bạn có thể đặt NamedParameters với Get dễ dàng: 204 +You can also receive NamedParameters with Get easily:
205 205
206 ```dart 206 ```dart
207 void main() { 207 void main() {
@@ -233,20 +233,20 @@ void main() { @@ -233,20 +233,20 @@ void main() {
233 } 233 }
234 ``` 234 ```
235 235
236 -Gửi data bằng tên 236 +Send data on route name
237 237
238 ```dart 238 ```dart
239 Get.toNamed("/profile/34954"); 239 Get.toNamed("/profile/34954");
240 ``` 240 ```
241 241
242 -Trên màn hình thứ hai, lấy dữ liệu theo tham số (parameters) 242 +On second screen take the data by parameter
243 243
244 ```dart 244 ```dart
245 print(Get.parameters['user']); 245 print(Get.parameters['user']);
246 // out: 34954 246 // out: 34954
247 ``` 247 ```
248 248
249 -hoặc gửi nhiều tham số như thế này 249 +or send multiple parameters like this
250 250
251 ```dart 251 ```dart
252 Get.toNamed("/profile/34954?flag=true&country=italy"); 252 Get.toNamed("/profile/34954?flag=true&country=italy");
@@ -257,7 +257,7 @@ var parameters = <String, String>{"flag": "true","country": "italy",}; @@ -257,7 +257,7 @@ var parameters = <String, String>{"flag": "true","country": "italy",};
257 Get.toNamed("/profile/34954", parameters: parameters); 257 Get.toNamed("/profile/34954", parameters: parameters);
258 ``` 258 ```
259 259
260 -Trên màn hình thứ hai, lấy dữ liệu theo các tham số như thường lệ 260 +On second screen take the data by parameters as usually
261 261
262 ```dart 262 ```dart
263 print(Get.parameters['user']); 263 print(Get.parameters['user']);
@@ -268,11 +268,11 @@ print(Get.parameters['country']); @@ -268,11 +268,11 @@ print(Get.parameters['country']);
268 268
269 269
270 270
271 -Và bây giờ, tất cả những gì bạn cần làm là sử dụng Get.toNamed () để điều hướng các routes đã đặt tên của bạn mà không cần bất kỳ "context" nào (bạn có thể gọi các routes của mình trực tiếp từ BLoC hoặc lớp Bộ điều khiển) và khi ứng dụng của bạn được biên dịch lên web, các routes sẽ xuất hiện trong url <3 271 +And now, all you need to do is use Get.toNamed() to navigate your named routes, without any context (you can call your routes directly from your BLoC or Controller class), and when your app is compiled to the web, your routes will appear in the url <3
272 272
273 ### Middleware 273 ### Middleware
274 274
275 -Nếu bạn muốn nghe Get events để kích hoạt các hành động, bạn có thể sử dụng routingCallback cho nó 275 +If you want listen Get events to trigger actions, you can to use routingCallback to it
276 276
277 ```dart 277 ```dart
278 GetMaterialApp( 278 GetMaterialApp(
@@ -284,7 +284,7 @@ GetMaterialApp( @@ -284,7 +284,7 @@ GetMaterialApp(
284 ) 284 )
285 ``` 285 ```
286 286
287 -Nếu bạn không sử dụng GetMaterialApp, bạn có thể sử dụng API thủ công để đính kèm trình quan sát Middleware. 287 +If you are not using GetMaterialApp, you can use the manual API to attach Middleware observer.
288 288
289 ```dart 289 ```dart
290 void main() { 290 void main() {
@@ -301,7 +301,7 @@ void main() { @@ -301,7 +301,7 @@ void main() {
301 } 301 }
302 ``` 302 ```
303 303
304 -Tạo một MiddleWare class 304 +Create a MiddleWare class
305 305
306 ```dart 306 ```dart
307 class MiddleWare { 307 class MiddleWare {
@@ -318,7 +318,7 @@ class MiddleWare { @@ -318,7 +318,7 @@ class MiddleWare {
318 } 318 }
319 ``` 319 ```
320 320
321 -Bây giờ, hãy sử dụng Get trên code của bạn: 321 +Now, use Get on your code:
322 322
323 ```dart 323 ```dart
324 class First extends StatelessWidget { 324 class First extends StatelessWidget {
@@ -391,11 +391,11 @@ class Third extends StatelessWidget { @@ -391,11 +391,11 @@ class Third extends StatelessWidget {
391 } 391 }
392 ``` 392 ```
393 393
394 -## Điều hướng không cần context 394 +## Navigation without context
395 395
396 ### SnackBars 396 ### SnackBars
397 397
398 -Để có một SnackBar đơn giản với Flutter, bạn phải lấy context của Scaffold, hoặc bạn phải sử dụng GlobalKey được gắn vào Scaffold của bạn 398 +To have a simple SnackBar with Flutter, you must get the context of Scaffold, or you must use a GlobalKey attached to your Scaffold
399 399
400 ```dart 400 ```dart
401 final snackBar = SnackBar( 401 final snackBar = SnackBar(
@@ -416,7 +416,7 @@ With Get: @@ -416,7 +416,7 @@ With Get:
416 Get.snackbar('Hi', 'i am a modern snackbar'); 416 Get.snackbar('Hi', 'i am a modern snackbar');
417 ``` 417 ```
418 418
419 -Với Get, tất cả những gì bạn phải làm là gọi thanh Get.snackbar từ bất kỳ đâu trong code của bạn hoặc tùy chỉnh nó theo cách bạn muốn! 419 +With Get, all you have to do is call your Get.snackbar from anywhere in your code or customize it however you want!
420 420
421 ```dart 421 ```dart
422 Get.snackbar( 422 Get.snackbar(
@@ -468,8 +468,8 @@ Get.snackbar( @@ -468,8 +468,8 @@ Get.snackbar(
468 /////////////////////////////////// 468 ///////////////////////////////////
469 ``` 469 ```
470 470
471 -Nếu bạn thích snackbar truyền thống hoặc muốn tùy chỉnh nó từ đầu, bao gồm chỉ thêm một dòng (Get.snackbar sử dụng tiêu đề và thông báo bắt buộc), bạn có thể sử dụng  
472 -`Get.rawSnackbar ()`; 'cung cấp API RAW trên đó Get. 471 +If you prefer the traditional snackbar, or want to customize it from scratch, including adding just one line (Get.snackbar makes use of a mandatory title and message), you can use
  472 +`Get.rawSnackbar();` which provides the RAW API on which Get.snackbar was built.
473 473
474 ### Dialogs 474 ### Dialogs
475 475
@@ -488,15 +488,15 @@ Get.defaultDialog( @@ -488,15 +488,15 @@ Get.defaultDialog(
488 ); 488 );
489 ``` 489 ```
490 490
491 -Bạn cũng có thể sử dụng Get.generalDialog thay vì showGeneralDialog. 491 +You can also use Get.generalDialog instead of showGeneralDialog.
492 492
493 -Đối với tất cả các tiện ích hộp thoại Flutter khác, bao gồm cả cupertinos, bạn có thể sử dụng Get.overlayContext thay vì context và mở nó ở bất kỳ đâu trong mã của bạn.  
494 -Đối với các widget không sử dụng Overlay, bạn có thể sử dụng Get.context.  
495 -Hai context này sẽ hoạt động trong 99% trường hợp để thay thế context của UI của bạn, ngoại trừ các trường hợp trong đó inheritWidget được sử dụng mà không có context điều hướng. 493 +For all other Flutter dialog widgets, including cupertinos, you can use Get.overlayContext instead of context, and open it anywhere in your code.
  494 +For widgets that don't use Overlay, you can use Get.context.
  495 +These two contexts will work in 99% of cases to replace the context of your UI, except for cases where inheritedWidget is used without a navigation context.
496 496
497 ### BottomSheets 497 ### BottomSheets
498 498
499 -Get.bottomSheet giống như showModalBottomSheet, nhưng không cần context. 499 +Get.bottomSheet is like showModalBottomSheet, but don't need of context.
500 500
501 ```dart 501 ```dart
502 Get.bottomSheet( 502 Get.bottomSheet(
@@ -519,14 +519,14 @@ Get.bottomSheet( @@ -519,14 +519,14 @@ Get.bottomSheet(
519 ); 519 );
520 ``` 520 ```
521 521
522 -## Điều hướng lồng (Nested Navigation) 522 +## Nested Navigation
523 523
524 -Làm cho điều hướng lồng (nested navigation) của Flutter thậm chí còn dễ dàng hơn.  
525 -Bạn không cần context và bạn sẽ tìm thấy stack điều hướng của mình theo Id. 524 +Get made Flutter's nested navigation even easier.
  525 +You don't need the context, and you will find your navigation stack by Id.
526 526
527 -- CHÍ Ú: Việc tạo các stack điều hướng song song có thể gây nguy hiểm. Lý tưởng nhất là không sử dụng NestedNavigators, hoặc sử dụng một cách tối thiểu. Nếu dự án của bạn yêu cầu, hãy tiếp tục, nhưng hãy nhớ rằng việc giữ nhiều stack điều hướng trong bộ nhớ có thể không phải là một ý tưởng hay cho việc tiêu thụ RAM. 527 +- NOTE: Creating parallel navigation stacks can be dangerous. The ideal is not to use NestedNavigators, or to use sparingly. If your project requires it, go ahead, but keep in mind that keeping multiple navigation stacks in memory may not be a good idea for RAM consumption.
528 528
529 -Xem nó code đơn giản nè: 529 +See how simple it is:
530 530
531 ```dart 531 ```dart
532 Navigator( 532 Navigator(
1 -* [Quản lý State](#state-management)  
2 - + [Quản lý Reactive State](#reactive-state-manager)  
3 - - [Lợi thế](#advantages)  
4 - - [Hiệu suất tối đa:](#maximum-performance)  
5 - - [Khai báo một biến phản ứng (reactive variable)](#declaring-a-reactive-variable)  
6 - - [Thât dễ khi có reactive state.](#having-a-reactive-state-is-easy)  
7 - - [Sử dụng values trong View](#using-the-values-in-the-view)  
8 - - [Điều kiện để tái tạo lại](#conditions-to-rebuild)  
9 - - [Nơi .obs có thể dùng](#where-obs-can-be-used)  
10 - - [Chí ú về Lists](#note-about-lists)  
11 - - [Tại sao tôi phải dùng .value](#why-i-have-to-use-value) 1 +* [State Management](#state-management)
  2 + + [Reactive State Manager](#reactive-state-manager)
  3 + - [Advantages](#advantages)
  4 + - [Maximum performance:](#maximum-performance)
  5 + - [Declaring a reactive variable](#declaring-a-reactive-variable)
  6 + - [Having a reactive state, is easy.](#having-a-reactive-state-is-easy)
  7 + - [Using the values in the view](#using-the-values-in-the-view)
  8 + - [Conditions to rebuild](#conditions-to-rebuild)
  9 + - [Where .obs can be used](#where-obs-can-be-used)
  10 + - [Note about Lists](#note-about-lists)
  11 + - [Why i have to use .value](#why-i-have-to-use-value)
12 - [Obx()](#obx) 12 - [Obx()](#obx)
13 - [Workers](#workers) 13 - [Workers](#workers)
14 - + [Quản lý State đơn giản](#simple-state-manager)  
15 - - [Lợi thế](#advantages-1)  
16 - - [Sử dụng](#usage)  
17 - - [Cách GetX sử dụng controllers](#how-it-handles-controllers)  
18 - - [Không cần StatefulWidget nữa!](#you-wont-need-statefulwidgets-anymore)  
19 - - [Tại sao GetX tồn tại?](#why-it-exists)  
20 - - [Cách sử dụng khác](#other-ways-of-using-it)  
21 - - [IDs độc nhất](#unique-ids)  
22 - + [Trộn hai trình quản lý state](#mixing-the-two-state-managers) 14 + + [Simple State Manager](#simple-state-manager)
  15 + - [Advantages](#advantages-1)
  16 + - [Usage](#usage)
  17 + - [How it handles controllers](#how-it-handles-controllers)
  18 + - [You won't need StatefulWidgets anymore](#you-wont-need-statefulwidgets-anymore)
  19 + - [Why it exists](#why-it-exists)
  20 + - [Other ways of using it](#other-ways-of-using-it)
  21 + - [Unique IDs](#unique-ids)
  22 + + [Mixing the two state managers](#mixing-the-two-state-managers)
23 + [GetBuilder vs GetX vs Obx vs MixinBuilder](#getbuilder-vs-getx-vs-obx-vs-mixinbuilder) 23 + [GetBuilder vs GetX vs Obx vs MixinBuilder](#getbuilder-vs-getx-vs-obx-vs-mixinbuilder)
24 24
25 -# Quản lý State 25 +# State Management
26 26
27 -GetX không sử dụng Streams hoặc ChangeNotifier như các quản lý state khác. Tại sao? Ngoài việc xây dựng các ứng dụng cho android, iOS, web, linux, macos và linux, với GetX bạn có thể xây dựng các ứng dụng máy chủ với cú pháp tương tự như Flutter / GetX. Để cải thiện thời gian phản hồi và giảm mức tiêu thụ RAM, chúng tôi đã tạo GetValue và GetStream, là các giải pháp có độ trễ thấp mang lại nhiều hiệu suất với chi phí vận hành thấp. Chúng tôi sử dụng cơ sở này để xây dựng tất cả các nguồn lực của mình, bao gồm cả quản lý state. 27 +GetX does not use Streams or ChangeNotifier like other state managers. Why? In addition to building applications for android, iOS, web, linux, macos and linux, with GetX you can build server applications with the same syntax as Flutter/GetX. In order to improve response time and reduce RAM consumption, we created GetValue and GetStream, which are low latency solutions that deliver a lot of performance, at a low operating cost. We use this base to build all of our resources, including state management.
28 28
29 -* _Phức hợp_: Một số quản lý state rất phức tạp và có rất nhiều cơ sở hạ tầng. Với GetX, bạn không phải xác định một class cho mỗi event, code rất rõ ràng và rõ ràng, và bạn làm được nhiều việc hơn bằng cách viết ít hơn. Nhiều người đã từ bỏ Flutter vì chủ đề này, và cuối cùng họ đã có một giải pháp đơn giản đến mức đần độn để quản lý các state.  
30 -* _Không trình tạo mã_: Bạn dành một nửa thời gian phát triển để viết logic ứng dụng của mình. Một số quản lý state dựa vào trình tạo mã để có mã có thể đọc được ở mức tối thiểu. Việc thay đổi một biến và phải chạy build_runner có thể gây mất hiệu quả, chuyện này rất ngốn thời gian chờ đợi sau khi quét sạch sẽ rất lâu và bạn phải uống rất nhiều cà phê. 29 +* _Complexity_: Some state managers are complex and have a lot of boilerplate. With GetX you don't have to define a class for each event, the code is highly clean and clear, and you do a lot more by writing less. Many people have given up on Flutter because of this topic, and they now finally have a stupidly simple solution for managing states.
  30 +* _No code generators_: You spend half your development time writing your application logic. Some state managers rely on code generators to have minimally readable code. Changing a variable and having to run build_runner can be unproductive, and often the waiting time after a flutter clean will be long, and you will have to drink a lot of coffee.
31 31
32 -Với GetX, mọi thứ đều hoạt động và độc lập với trình tạo mã, giúp tăng năng suất của bạn trong mọi khía cạnh phát triển của bạn. 32 +With GetX everything is reactive, and nothing depends on code generators, increasing your productivity in all aspects of your development.
33 33
34 -* _Không phụ thuộc vào context_: Có thể bạn đã cần gửi context của chế độ xem của mình tới controller, làm cho khả năng kết hợp của View với business logic của bạn cao hơn. Bạn có thể phải sử dụng một dependency cho một nơi không có context và phải chuyển context qua các class và hàm khác nhau. Điều này không tồn tại với GetX. Bạn có quyền truy cập vào controller của mình từ bên trong controller mà không cần bất kỳ context nào. Bạn không cần phải gửi context theo tham số vì không có gì theo nghĩa đen.  
35 -* _Kiểm soát hạt_: Hầu hết các quản lý state đều dựa trên ChangeNotifier. ChangeNotifier sẽ thông báo cho tất cả các widget phụ thuộc vào nó khi thông báo cho các widget được gọi. Nếu bạn có 40 widget con trên một màn hình, trong đó có một biến thuộc class ChangeNotifier của bạn, khi bạn cập nhật một widget con, tất cả chúng sẽ được xây dựng lại. 34 +* _It does not depend on context_: You probably already needed to send the context of your view to a controller, making the View's coupling with your business logic high. You have probably had to use a dependency for a place that has no context, and had to pass the context through various classes and functions. This just doesn't exist with GetX. You have access to your controllers from within your controllers without any context. You don't need to send the context by parameter for literally nothing.
  35 +* _Granular control_: most state managers are based on ChangeNotifier. ChangeNotifier will notify all widgets that depend on it when notifyListeners is called. If you have 40 widgets on one screen, which have a variable of your ChangeNotifier class, when you update one, all of them will be rebuilt.
36 36
37 -Với GetX, ngay cả các widget lồng nhau cũng được tôn trọng. Nếu bạn có Obx đang xem ListView của bạn và người khác đang xem hộp kiểm bên trong ListView, thì khi thay đổi giá trị CheckBox, chỉ nó mới được cập nhật, khi thay đổi giá trị List, chỉ ListView sẽ được cập nhật. 37 +With GetX, even nested widgets are respected. If you have Obx watching your ListView, and another watching a checkbox inside the ListView, when changing the CheckBox value, only it will be updated, when changing the List value, only the ListView will be updated.
38 38
39 -* _Chỉ tái tạo lại nếu biến CẦN thay đổi_: GetX có tính năng kiểm soát streams, điều đó có nghĩa là nếu bạn hiển thị Text là 'Kaiser', nếu bạn thay đổi lại biến có thể quan sát thành 'Kaiser', widget sẽ không được tạo lại. Đó là bởi vì GetX biết rằng 'Kaiser' đã được hiển thị trong Văn bản và sẽ không thực hiện các thao tác tái tạo không cần thiết. 39 +* _It only reconstructs if its variable REALLY changes_: GetX has flow control, that means if you display a Text with 'Paola', if you change the observable variable to 'Paola' again, the widget will not be reconstructed. That's because GetX knows that 'Paola' is already being displayed in Text, and will not do unnecessary reconstructions.
40 40
41 -Hầu hết (nếu không phải tất cả) các trình quản lý state hiện tại sẽ xây dựng lại trên màn hình. 41 +Most (if not all) current state managers will rebuild on the screen.
42 42
43 -## Quản lý Reactive State 43 +## Reactive State Manager
44 44
45 -Lập trình phản ứng (Reactive programming) có thể khiến nhiều người xa lánh vì nó được cho là phức tạp. GetX biến lập trình phản ứng thành một thứ khá đơn giản: 45 +Reactive programming can alienate many people because it is said to be complicated. GetX turns reactive programming into something quite simple:
46 46
47 -* Bạn sẽ không cần tạo StreamControllers.  
48 -* Bạn sẽ không cần tạo StreamBuilder cho mỗi biến  
49 -* Bạn sẽ không cần phải tạo một class cho mỗi state.  
50 -* Bạn sẽ không cần tạo get cho một giá trị ban đầu. 47 +* You won't need to create StreamControllers.
  48 +* You won't need to create a StreamBuilder for each variable
  49 +* You will not need to create a class for each state.
  50 +* You will not need to create a get for an initial value.
51 51
52 -Lập trình phản ứng với Get dễ dàng như sử dụng setState. 52 +Reactive programming with Get is as easy as using setState.
53 53
54 -Hãy tưởng tượng rằng bạn có một biến tên và muốn rằng mỗi khi bạn thay đổi nó, tất cả các widget sử dụng nó sẽ được tự động thay đổi. 54 +Let's imagine that you have a name variable and want that every time you change it, all widgets that use it are automatically changed.
55 55
56 -Đây là count variable của bạn: 56 +This is your count variable:
57 57
58 ``` dart 58 ``` dart
59 -var name = 'Khang Huỳnh'; 59 +var name = 'Jonatas Borges';
60 ``` 60 ```
61 61
62 -Để làm cho nó có thể quan sát được, bạn chỉ cần thêm ".obs" vào cuối nó: 62 +To make it observable, you just need to add ".obs" to the end of it:
63 63
64 ``` dart 64 ``` dart
65 -var name = 'Khang Huỳnh'.obs; 65 +var name = 'Jonatas Borges'.obs;
66 ``` 66 ```
67 67
68 -Chỉ vậy thôi, chỉ *vậy thôi* người ơi~ 68 +That's all. It's *that* simple.
69 69
70 -Từ bây giờ, chúng ta có thể tham chiếu đến các biến reactive - ". Obs" (có thể thay thế) này là _Rx_. 70 +From now on, we might refer to this reactive-".obs"(ervables) variables as _Rx_.
71 71
72 -Chúng tôi đã làm gì phía dưới class code? Chúng tôi đã tạo một `Stream` của `String`, được gán giá trị ban đầu `"Khang Huỳnh"`, chúng tôi đã thông báo cho tất cả các widget con sử dụng `"Khang Huỳnh"` rằng chúng hiện "thuộc về" biến này và khi giá trị _Rx_ thay đổi, chúng phải thay đổi theo.  
73 -Đây là **phép màu của GetX**, nhờ vào khả năng của Dart. 72 +What did we do under the hood? We created a `Stream` of `String` s, assigned the initial value `"Jonatas Borges"` , we notified all widgets that use `"Jonatas Borges"` that they now "belong" to this variable, and when the _Rx_ value changes, they will have to change as well.
74 73
75 -Tuy nhiên, như chúng ta đã biết, một `Widget` chỉ có thể được thay đổi nếu nó nằm bên trong một hàm, bởi vì các class tĩnh không có quyền" tự động thay đổi ". 74 +This is the **magic of GetX**, thanks to Dart's capabilities.
76 75
77 -Bạn sẽ cần tạo một `StreamBuilder`, đăng ký biến này để lắng nghe các thay đổi và tạo một "stream" các` StreamBuilder` lồng nhau nếu bạn muốn thay đổi một số biến trong cùng một phạm vi, phải không? 76 +But, as we know, a `Widget` can only be changed if it is inside a function, because static classes do not have the power to "auto-change".
78 77
79 -Không, bạn không cần `StreamBuilder`, nhưng bạn đã đúng về các class tĩnh. 78 +You will need to create a `StreamBuilder` , subscribe to this variable to listen for changes, and create a "cascade" of nested `StreamBuilder` if you want to change several variables in the same scope, right?
80 79
81 -Theo quan điểm, chúng ta thường có rất nhiều bảng soạn sẵn khi chúng ta muốn thay đổi một Widget cụ thể, đó là cách Flutter.  
82 -Với ** GetX **, bạn cũng có thể quên mã soạn sẵn này. 80 +No, you don't need a `StreamBuilder` , but you are right about static classes.
83 81
84 -`StreamBuilder (…)`? `initialValue:…`? `builder:…`? Không, bạn chỉ cần đặt biến này bên trong Widget `Obx ()`. 82 +Well, in the view, we usually have a lot of boilerplate when we want to change a specific Widget, that's the Flutter way.
  83 +With **GetX** you can also forget about this boilerplate code.
  84 +
  85 +`StreamBuilder( … )` ? `initialValue: …` ? `builder: …` ? Nope, you just need to place this variable inside an `Obx()` Widget.
85 86
86 ``` dart 87 ``` dart
87 Obx (() => Text (controller.name)); 88 Obx (() => Text (controller.name));
88 ``` 89 ```
89 90
90 -_Bạn cần nhớ gì?_ Chỉ `Obx(() =>` . 91 +_What do you need to memorize?_ Only `Obx(() =>` .
91 92
92 -Bạn chỉ đang chuyển Widget đó thông qua một hàm mũi tên vào một `Obx ()` ("Observer" của _Rx_). 93 +You are just passing that Widget through an arrow-function into an `Obx()` (the "Observer" of the _Rx_).
93 94
94 -`Obx` khá thông minh và sẽ chỉ thay đổi nếu giá trị của `controller.name` thay đổi. 95 +`Obx` is pretty smart, and will only change if the value of `controller.name` changes.
95 96
96 -Nếu `name` là` "Kaiser" `và bạn thay đổi nó thành` "Kaiser" `(` name.value = "Kaiser" `), vì nó giống như` giá trị` như trước, sẽ không có gì thay đổi trên màn hình, và `Obx`, để tiết kiệm tài nguyên, sẽ đơn giản bỏ qua giá trị mới và không xây dựng lại Widget. **Tuyệt vời ông mặt trời chứ?** 97 +If `name` is `"John"` , and you change it to `"John"` ( `name.value = "John"` ), as it's the same `value` as before, nothing will change on the screen, and `Obx` , to save resources, will simply ignore the new value and not rebuild the Widget. **Isn't that amazing?**
97 98
98 > So, what if I have 5 _Rx_ (observable) variables within an `Obx` ? 99 > So, what if I have 5 _Rx_ (observable) variables within an `Obx` ?
99 100
100 -Nó sẽ chỉ cập nhật khi ** bất kỳ ** nào trong số chúng thay đổi. 101 +It will just update when **any** of them changes.
101 102
102 > And if I have 30 variables in a class, when I update one, will it update **all** the variables that are in that class? 103 > And if I have 30 variables in a class, when I update one, will it update **all** the variables that are in that class?
103 104
104 -Không, chỉ **Widget cụ thể** sử dụng biến _Rx_ đó. 105 +Nope, just the **specific Widget** that uses that _Rx_ variable.
105 106
106 -Vì vậy, **GetX** chỉ cập nhật màn hình, khi biến _Rx_ thay đổi giá trị của nó. 107 +So, **GetX** only updates the screen, when the _Rx_ variable changes it's value.
107 108
108 ``` 109 ```
109 110
@@ -113,42 +114,44 @@ final isOpen = false.obs; @@ -113,42 +114,44 @@ final isOpen = false.obs;
113 void onButtonTap() => isOpen.value=false; 114 void onButtonTap() => isOpen.value=false;
114 ``` 115 ```
115 116
116 -### Lợi thế 117 +### Advantages
117 118
118 -**GetX()** giúp bạn khi bạn cần kiểm soát **chi tiết** đối với những gì đang được cập nhật. 119 +**GetX()** helps you when you need **granular** control over what's being updated.
119 120
120 -Nếu bạn không cần `ID duy nhất`, vì tất cả các biến của bạn sẽ được sửa đổi khi bạn thực hiện một hành động, thì hãy sử dụng` GetBuilder`,  
121 -bởi vì nó là một Trình cập nhật state đơn giản (trong các khối, như `setState ()` '), được tạo chỉ trong một vài dòng mã.  
122 -Nó được làm đơn giản, ít ảnh hưởng đến CPU nhất và chỉ để thực hiện một mục đích duy nhất (xây dựng lại _State_) và sử dụng tài nguyên tối thiểu có thể. 121 +If you do not need `unique IDs` , because all your variables will be modified when you perform an action, then use `GetBuilder` ,
  122 +because it's a Simple State Updater (in blocks, like `setState()` ), made in just a few lines of code.
  123 +It was made simple, to have the least CPU impact, and just to fulfill a single purpose (a _State_ rebuild) and spend the minimum resources possible.
123 124
124 -Nếu bạn cần một Trình quản lý state **mạnh mẽ**, bạn không thể làm sai với **GetX**. 125 +If you need a **powerful** State Manager, you can't go wrong with **GetX**.
125 126
126 -Nó không hoạt động với các biến, nhưng __flows__, mọi thứ trong đó đều là `Streams`. 127 +It doesn't work with variables, but __flows__, everything in it are `Streams` under the hood.
127 128
128 -Bạn có thể sử dụng _rxDart_ kết hợp với nó, vì mọi thứ đều là `Luồng`,  
129 -bạn có thể nghe `event` của từng" biến _Rx_ ",  
130 -bởi vì mọi thứ trong đó đều là `Streams`. 129 +You can use _rxDart_ in conjunction with it, because everything are `Streams`,
  130 +you can listen to the `event` of each "_Rx_ variable",
  131 +because everything in it are `Streams`.
131 132
132 -Nó thực sự là một cách tiếp cận _BLoC_, dễ dàng hơn _MobX_ và không có trình tạo code hoặc decorations.  
133 -Bạn có thể biến **mọi thứ** thành một _"Observable" _ chỉ với một `.obs`. 133 +It is literally a _BLoC_ approach, easier than _MobX_, and without code generators or decorations.
  134 +You can turn **anything** into an _"Observable"_ with just a `.obs` .
134 135
135 -### Hiệu suất tối đa: 136 +### Maximum performance:
136 137
137 -Ngoài việc có một thuật toán thông minh để xây dựng lại tối thiểu, **GetX** sử dụng trình so sánh để đảm bảo rằng Bang đã thay đổi. 138 +In addition to having a smart algorithm for minimal rebuilds, **GetX** uses comparators
  139 +to make sure the State has changed.
138 140
139 -Nếu bạn gặp bất kỳ lỗi nào trong ứng dụng của mình và gửi một bản thay đổi state, **GetX** sẽ đảm bảo rằng nó sẽ không gặp sự cố. 141 +If you experience any errors in your app, and send a duplicate change of State,
  142 +**GetX** will ensure it will not crash.
140 143
141 -Với **GetX** State chỉ thay đổi nếu `giá trị` thay đổi.  
142 -Đó là sự khác biệt chính giữa **GetX** và việc sử dụng _ `computed` từ MobX_.  
143 -Khi kết hợp hai __observables__, và một thay đổi; trình nghe của _observable_ đó cũng sẽ thay đổi. 144 +With **GetX** the State only changes if the `value` change.
  145 +That's the main difference between **GetX**, and using _ `computed` from MobX_.
  146 +When joining two __observables__, and one changes; the listener of that _observable_ will change as well.
144 147
145 -Với **GetX**, nếu bạn nối hai biến, `GetX ()` (tương tự như `Observer ()`) sẽ chỉ xây dựng lại nếu nó ngụ ý thay đổi state thực sự. 148 +With **GetX**, if you join two variables, `GetX()` (similar to `Observer()` ) will only rebuild if it implies a real change of State.
146 149
147 -### Khai báo một biến phản ứng (reactive variable) 150 +### Declaring a reactive variable
148 151
149 -Bạn có 3 cách để thay đổi variable thành "observable". 152 +You have 3 ways to turn a variable into an "observable".
150 153
151 -1 - Sử dụng **`Rx{Type}`**. 154 +1 - The first is using **`Rx{Type}`**.
152 155
153 ``` dart 156 ``` dart
154 // initial value is recommended, but not mandatory 157 // initial value is recommended, but not mandatory
@@ -160,7 +163,7 @@ final items = RxList<String>([]); @@ -160,7 +163,7 @@ final items = RxList<String>([]);
160 final myMap = RxMap<String, int>({}); 163 final myMap = RxMap<String, int>({});
161 ``` 164 ```
162 165
163 -2 - Sử dụng **`Rx`** và dùng Darts Generics, `Rx<Type>` 166 +2 - The second is to use **`Rx`** and use Darts Generics, `Rx<Type>`
164 167
165 ``` dart 168 ``` dart
166 final name = Rx<String>(''); 169 final name = Rx<String>('');
@@ -175,7 +178,7 @@ final myMap = Rx<Map<String, int>>({}); @@ -175,7 +178,7 @@ final myMap = Rx<Map<String, int>>({});
175 final user = Rx<User>(); 178 final user = Rx<User>();
176 ``` 179 ```
177 180
178 -3 - Cách tối ưu nhất, thêm **`.obs`**`value` : 181 +3 - The third, more practical, easier and preferred approach, just add **`.obs`** as a property of your `value` :
179 182
180 ``` dart 183 ``` dart
181 final name = ''.obs; 184 final name = ''.obs;
@@ -190,16 +193,17 @@ final myMap = <String, int>{}.obs; @@ -190,16 +193,17 @@ final myMap = <String, int>{}.obs;
190 final user = User().obs; 193 final user = User().obs;
191 ``` 194 ```
192 195
193 -##### Thât dễ khi có reactive state. 196 +##### Having a reactive state, is easy.
194 197
195 -Như chúng ta biết, _Dart_ đang hướng tới _null safety_.  
196 -Để chuẩn bị, từ bây giờ, bạn phải luôn bắt đầu các biến _Rx_ của mình bằng một **initial value**. 198 +As we know, _Dart_ is now heading towards _null safety_.
  199 +To be prepared, from now on, you should always start your _Rx_ variables with an **initial value**.
197 200
198 > Transforming a variable into an _observable_ + _initial value_ with **GetX** is the simplest, and most practical approach. 201 > Transforming a variable into an _observable_ + _initial value_ with **GetX** is the simplest, and most practical approach.
199 202
200 -Theo đúng nghĩa đen, bạn sẽ thêm một "` .obs` "vào cuối biến của mình và **vậy thôi người ơi~**, bạn đã làm cho nó có thể quan sát được, và `.value` của nó sẽ là _initial value_). 203 +You will literally add a " `.obs` " to the end of your variable, and **that’s it**, you’ve made it observable,
  204 +and its `.value` , well, will be the _initial value_).
201 205
202 -### Sử dụng values trong View 206 +### Using the values in the view
203 207
204 ``` dart 208 ``` dart
205 // controller file 209 // controller file
@@ -230,33 +234,33 @@ GetX<Controller>( @@ -230,33 +234,33 @@ GetX<Controller>(
230 ), 234 ),
231 ``` 235 ```
232 236
233 -Nếu chúng ta cộng `count1.value++` , nó sẽ in: 237 +If we increment `count1.value++` , it will print:
234 238
235 * `count 1 rebuild` 239 * `count 1 rebuild`
236 240
237 * `count 3 rebuild` 241 * `count 3 rebuild`
238 242
239 -bởi vì `count1` có giá trị là` 1` và `1 + 0 = 1`, thay đổi giá trị getter` sum`. 243 +because `count1` has a value of `1` , and `1 + 0 = 1` , changing the `sum` getter value.
240 244
241 -Nếu ta thay đổi `count2.value++` , nó sẽ in: 245 +If we change `count2.value++` , it will print:
242 246
243 * `count 2 rebuild` 247 * `count 2 rebuild`
244 248
245 * `count 3 rebuild` 249 * `count 3 rebuild`
246 250
247 -bởi vì `count2.value` đã thay đổi, và kết quả của` sum` bây giờ là `2`. 251 +because `count2.value` changed, and the result of the `sum` is now `2` .
248 252
249 -* LƯU Ý: Theo mặc định, event đầu tiên sẽ xây dựng lại widget con, ngay cả khi nó là cùng một `giá trị`. 253 +* NOTE: By default, the very first event will rebuild the widget, even if it is the same `value`.
250 254
251 -Hành vi này tồn tại do các biến Boolean. 255 + This behavior exists due to Boolean variables.
252 256
253 -Ví dụ, bạn code thế này: 257 +Imagine you did this:
254 258
255 ``` dart 259 ``` dart
256 var isLogged = false.obs; 260 var isLogged = false.obs;
257 ``` 261 ```
258 262
259 -Và sau đó, bạn đã kiểm tra xem người dùng có "đăng nhập" để kích hoạt event trong `ever` không. 263 +And then, you checked if a user is "logged in" to trigger an event in `ever` .
260 264
261 ``` dart 265 ``` dart
262 @override 266 @override
@@ -274,16 +278,16 @@ fireRoute(logged) { @@ -274,16 +278,16 @@ fireRoute(logged) {
274 } 278 }
275 ``` 279 ```
276 280
277 -nếu `hasToken` là` false`, sẽ không có thay đổi thành `isLogged`, vì vậy `ever ()` sẽ không bao giờ được gọi.  
278 -Để tránh loại hành vi này, thay đổi đầu tiên đối với _observable_ sẽ luôn kích hoạt một event,  
279 -ngay cả khi nó chứa cùng một `.value`. 281 +if `hasToken` was `false` , there would be no change to `isLogged` , so `ever()` would never be called.
  282 +To avoid this type of behavior, the first change to an _observable_ will always trigger an event,
  283 +even if it contains the same `.value` .
280 284
281 -Bạn có thể xóa hành vi này nếu muốn, bằng cách sử dụng: 285 +You can remove this behavior if you want, using:
282 `isLogged.firstRebuild = false;` 286 `isLogged.firstRebuild = false;`
283 287
284 -### Điều kiện để tái tạo lại 288 +### Conditions to rebuild
285 289
286 -Ngoài ra, Get cung cấp khả năng kiểm soát state đã được tinh chỉnh. Bạn có thể điều kiện một event (chẳng hạn như thêm một đối tượng vào danh sách), với một điều kiện nhất định. 290 +In addition, Get provides refined state control. You can condition an event (such as adding an object to a list), on a certain condition.
287 291
288 ``` dart 292 ``` dart
289 // First parameter: condition, must return true or false. 293 // First parameter: condition, must return true or false.
@@ -291,9 +295,9 @@ Ngoài ra, Get cung cấp khả năng kiểm soát state đã được tinh chá» @@ -291,9 +295,9 @@ Ngoài ra, Get cung cấp khả năng kiểm soát state đã được tinh chá»
291 list.addIf(item < limit, item); 295 list.addIf(item < limit, item);
292 ``` 296 ```
293 297
294 -Không có decoration, không có trình tạo mã, không có phức tạp hóa vấn đề: smile: 298 +Without decorations, without a code generator, without complications :smile:
295 299
296 -Bạn có biết ứng dụng counter của Flutter không? Class controller của bạn có thể trông giống như sau: 300 +Do you know Flutter's counter app? Your Controller class might look like this:
297 301
298 ``` dart 302 ``` dart
299 class CountController extends GetxController { 303 class CountController extends GetxController {
@@ -301,19 +305,19 @@ class CountController extends GetxController { @@ -301,19 +305,19 @@ class CountController extends GetxController {
301 } 305 }
302 ``` 306 ```
303 307
304 -Đơn giản hơn: 308 +With a simple:
305 309
306 ``` dart 310 ``` dart
307 controller.count.value++ 311 controller.count.value++
308 ``` 312 ```
309 313
310 -Bạn có thể cập nhật counter trong UI của mình, bất kể nó được lưu trữ ở đâu. 314 +You could update the counter variable in your UI, regardless of where it is stored.
311 315
312 -### Nơi .obs có thể dùng 316 +### Where .obs can be used
313 317
314 -Bạn có thể biến đổi bất cứ thứ gì trên obs. Đây là hai cách để làm điều đó: 318 +You can transform anything on obs. Here are two ways of doing it:
315 319
316 -* Bạn có thể chuyển đổi các giá trị class của mình thành obs 320 +* You can convert your class values to obs
317 321
318 ``` dart 322 ``` dart
319 class RxUser { 323 class RxUser {
@@ -322,7 +326,7 @@ class RxUser { @@ -322,7 +326,7 @@ class RxUser {
322 } 326 }
323 ``` 327 ```
324 328
325 -* hoặc bạn có thể biến cả 1 class thành observable 329 +* or you can convert the entire class to be an observable
326 330
327 ``` dart 331 ``` dart
328 class User { 332 class User {
@@ -335,12 +339,12 @@ class User { @@ -335,12 +339,12 @@ class User {
335 final user = User(name: "Camila", age: 18).obs; 339 final user = User(name: "Camila", age: 18).obs;
336 ``` 340 ```
337 341
338 -### Chí ú về Lists 342 +### Note about Lists
339 343
340 -List hoàn toàn có thể quan sát được cũng như các đối tượng bên trong nó. Bằng cách đó, nếu bạn thêm một giá trị vào danh sách, nó sẽ tự động xây dựng lại các widget con sử dụng nó. 344 +Lists are completely observable as are the objects within it. That way, if you add a value to a list, it will automatically rebuild the widgets that use it.
341 345
342 -Bạn cũng không cần phải sử dụng ".value" với các danh sách, api phi tiêu tuyệt vời đã cho phép chúng tôi loại bỏ điều đó.  
343 -Tiếc thay, các kiểu nguyên thủy như String và int không thể được mở rộng, khiến việc sử dụng .value là bắt buộc, nhưng điều đó sẽ không thành vấn đề nếu bạn làm việc với getters và setters cho những thứ này. 346 +You also don't need to use ".value" with lists, the amazing dart api allowed us to remove that.
  347 +Unfortunaly primitive types like String and int cannot be extended, making the use of .value mandatory, but that won't be a problem if you work with gets and setters for these.
344 348
345 ``` dart 349 ``` dart
346 // On the controller 350 // On the controller
@@ -354,7 +358,7 @@ ListView.builder ( @@ -354,7 +358,7 @@ ListView.builder (
354 ) 358 )
355 ``` 359 ```
356 360
357 -Khi bạn đang làm cho các class của riêng mình có thể quan sát được, có một cách khác để cập nhật chúng: 361 +When you are making your own classes observable, there is a different way to update them:
358 362
359 ``` dart 363 ``` dart
360 // on the model file 364 // on the model file
@@ -381,32 +385,32 @@ Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}")) @@ -381,32 +385,32 @@ Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}"))
381 user().name; // notice that is the user variable, not the class (variable has lowercase u) 385 user().name; // notice that is the user variable, not the class (variable has lowercase u)
382 ``` 386 ```
383 387
384 -Bạn không cần phải làm việc với các bộ nếu bạn không muốn. bạn có thể sử dụng api "assign" và "assignAll".  
385 -Api "assign" sẽ xóa danh sách của bạn và thêm một đối tượng duy nhất mà bạn muốn bắt đầu ở đó.  
386 -Api "allowAll" sẽ xóa danh sách hiện có và thêm bất kỳ đối tượng có thể lặp lại nào mà bạn đưa vào đó. 388 +You don't have to work with sets if you don't want to. you can use the "assign 'and" assignAll "api.
  389 +The "assign" api will clear your list, and add a single object that you want to start there.
  390 +The "assignAll" api will clear the existing list and add any iterable objects that you inject into it.
387 391
388 -### Tại sao tôi phải dùng .value 392 +### Why i have to use .value
389 393
390 -Chúng ta có thể loại bỏ việc sử dụng 'value' đối với `String` và` int` bằng một trình tạo mã và decoration đơn giản, nhưng mục đích của thư viện này chính là tránh các dependency bên ngoài. Chúng tôi muốn cung cấp một môi trường sẵn sàng cho việc lập trình, liên quan đến các yếu tố cần thiết (quản lý các route, dependency và state), theo cách đơn giản, nhẹ và hiệu quả mà không cần gói bên ngoài. 394 +We could remove the obligation to use 'value' to `String` and `int` with a simple decoration and code generator, but the purpose of this library is precisely avoid external dependencies. We want to offer an environment ready for programming, involving the essentials (management of routes, dependencies and states), in a simple, lightweight and performant way, without a need of an external package.
391 395
392 -Theo nghĩa đen, bạn có thể thêm 3 chữ cái vào pubspec (get) của mình và dấu hai chấm và bắt đầu lập trình. Tất cả các giải pháp được bao gồm theo mặc định, từ quản lý route đến quản lý state, nhằm mục đích dễ dàng, năng suất và hiệu suất. 396 +You can literally add 3 letters to your pubspec (get) and a colon and start programming. All solutions included by default, from route management to state management, aim at ease, productivity and performance.
393 397
394 -Tổng trọng lượng của thư viện này ít hơn của một trình quản lý state duy nhất, mặc dù nó là một giải pháp hoàn chỉnh và đó là những gì bạn phải hiểu. 398 +The total weight of this library is less than that of a single state manager, even though it is a complete solution, and that is what you must understand.
395 399
396 -Nếu bạn bị làm phiền bởi `.value`, và giống như một trình tạo mã, MobX là một giải pháp thay thế tuyệt vời và bạn có thể sử dụng nó cùng với Get. Đối với những người muốn thêm một gói dependency duy nhất vào pubspec và bắt đầu lập trình mà không cần lo lắng về phiên bản của gói không tương thích với gói khác hoặc nếu lỗi cập nhật state đến từ trình quản lý state hoặc dependency, hoặc vẫn không muốn lo lắng về sự sẵn có của controller, cho dù theo nghĩa đen là "chỉ là lập trình", GetX là lựa chọn hoàn hảo. 400 +If you are bothered by `.value` , and like a code generator, MobX is a great alternative, and you can use it in conjunction with Get. For those who want to add a single dependency in pubspec and start programming without worrying about the version of a package being incompatible with another, or if the error of a state update is coming from the state manager or dependency, or still, do not want to worrying about the availability of controllers, whether literally "just programming", get is just perfect.
397 401
398 -Nếu bạn không gặp vấn đề gì với trình tạo mã MobX hoặc không gặp vấn đề gì với bảng soạn sẵn BLoC, bạn có thể chỉ cần sử dụng Get cho các route và quên rằng nó có trình quản lý state. Get SEM và RSM ra đời không cần thiết, công ty của tôi có một dự án với hơn 90 controller và trình tạo mã chỉ mất hơn 30 phút để hoàn thành nhiệm vụ của nó sau khi Flutter Clean trên một máy khá tốt, nếu dự án của bạn có 5, 10, 15 controller, bất kỳ nhà quản lý state sẽ cung cấp cho bạn tốt. Nếu bạn có một dự án lớn đến mức ngớ ngẩn và trình tạo mã là một vấn đề đối với bạn, thì bạn đã được trao giải pháp này. 402 +If you have no problem with the MobX code generator, or have no problem with the BLoC boilerplate, you can simply use Get for routes, and forget that it has state manager. Get SEM and RSM were born out of necessity, my company had a project with more than 90 controllers, and the code generator simply took more than 30 minutes to complete its tasks after a Flutter Clean on a reasonably good machine, if your project it has 5, 10, 15 controllers, any state manager will supply you well. If you have an absurdly large project, and code generator is a problem for you, you have been awarded this solution.
399 403
400 -Rõ ràng, nếu ai đó muốn đóng góp vào dự án và tạo trình tạo mã, hoặc thứ gì đó tương tự, tôi sẽ liên kết trong readme này như một giải pháp thay thế, nhu cầu của tôi không phải là nhu cầu của tất cả các nhà phát triển, nhưng ý tôi là thế, đã có những giải pháp tốt đã làm được điều đó, như MobX. 404 +Obviously, if someone wants to contribute to the project and create a code generator, or something similar, I will link in this readme as an alternative, my need is not the need for all devs, but for now I say, there are good solutions that already do that, like MobX.
401 405
402 ### Obx() 406 ### Obx()
403 407
404 -Nhập vào Get bằng cách sử dụng Bindings là không cần thiết. bạn có thể sử dụng widget Obx thay vì GetX, widget chỉ nhận được chức năng ẩn danh tạo widget.  
405 -Rõ ràng, nếu bạn không sử dụng một kiểu, bạn sẽ cần phải có một phiên bản của controller để sử dụng các biến hoặc sử dụng `Get.find <Controller> ()` .value hoặc Controller.to.value để truy xuất giá trị . 408 +Typing in Get using Bindings is unnecessary. you can use the Obx widget instead of GetX which only receives the anonymous function that creates a widget.
  409 +Obviously, if you don't use a type, you will need to have an instance of your controller to use the variables, or use `Get.find<Controller>()` .value or Controller.to.value to retrieve the value.
406 410
407 ### Workers 411 ### Workers
408 412
409 -Workers sẽ hỗ trợ bạn, kích hoạt các lệnh gọi lại cụ thể khi một event xảy ra. 413 +Workers will assist you, triggering specific callbacks when an event occurs.
410 414
411 ``` dart 415 ``` dart
412 /// Called every time `count1` changes. 416 /// Called every time `count1` changes.
@@ -422,63 +426,63 @@ debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1)); @@ -422,63 +426,63 @@ debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1));
422 interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1)); 426 interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
423 ``` 427 ```
424 428
425 -Tất cả các workers (except `debounce` ) có `condition` tham số được đặt tên, mà có thể là loại `bool` hoặc lệnh gọi lại trả về một `bool` .  
426 -`condition` này mô tả khi `callback` kích hoạt. 429 +All workers (except `debounce` ) have a `condition` named parameter, which can be a `bool` or a callback that returns a `bool` .
  430 +This `condition` defines when the `callback` function executes.
427 431
428 -Tất cả các workers đều trả về trường hợp `Worker`, mà bạn có thể đóng ( thông qua `dispose()` ) của worker. 432 +All workers returns a `Worker` instance, that you can use to cancel ( via `dispose()` ) the worker.
429 433
430 434
431 * **`ever`** 435 * **`ever`**
432 436
433 - được gọi mỗi khi biến _Rx_ tạo ra một giá trị mới. 437 + is called every time the _Rx_ variable emits a new value.
434 438
435 * **`everAll`** 439 * **`everAll`**
436 440
437 -Giống như `ever`, nhưng nó có một` List` gồm các giá trị _Rx_ Được gọi mỗi khi biến của nó bị thay đổi. Chỉ vậy thôi người ơi~ 😊 441 + Much like `ever` , but it takes a `List` of _Rx_ values Called every time its variable is changed. That's it.
438 442
439 * **`once`** 443 * **`once`**
440 444
441 -'once' chỉ được gọi lần đầu tiên biến được thay đổi. 445 +'once' is called only the first time the variable has been changed.
442 446
443 * **`debounce`** 447 * **`debounce`**
444 448
445 -'debounce' rất hữu ích trong các hàm tìm kiếm, nơi bạn chỉ muốn API được gọi khi người dùng nhập xong. Nếu người dùng nhập "Kaiser", bạn sẽ có 6 tìm kiếm trong các API, theo ký tự K, a, i, s, e và r. Với Get, điều này không xảy ra, bởi vì bạn sẽ có một Worker "debounce" sẽ chỉ được kích hoạt khi kết thúc nhập. 449 +'debounce' is very useful in search functions, where you only want the API to be called when the user finishes typing. If the user types "Jonny", you will have 5 searches in the APIs, by the letter J, o, n, n, and y. With Get this does not happen, because you will have a "debounce" Worker that will only be triggered at the end of typing.
446 450
447 * **`interval`** 451 * **`interval`**
448 452
449 -'interval' khác với debounce. Debounce xảy ra nếu người dùng thực hiện 1000 thay đổi đối với một biến trong vòng 1 giây, y sẽ chỉ gửi biến cuối cùng sau bộ hẹn giờ quy định (mặc định là 800 mili giây). Thay vào đó, interval sẽ bỏ qua tất cả các hành động của người dùng trong interval quy định. Nếu bạn gửi event trong 1 phút, 1000 mỗi giây, tính năng gỡ lỗi sẽ chỉ gửi cho bạn event cuối cùng, khi người dùng ngừng phân chia event. interval sẽ phân phối các event mỗi giây và nếu được đặt thành 3 giây, nó sẽ phân phối 20 event trong phút đó. Điều này được khuyến nghị để tránh lạm dụng, trong các chức năng mà người dùng có thể nhanh chóng nhấp vào một thứ gì đó và có được một số lợi thế (hãy tưởng tượng rằng người dùng có thể kiếm được xu bằng cách nhấp vào thứ gì đó, nếu y nhấp 300 lần trong cùng một phút, y sẽ có 300 xu, bằng cách sử dụng interval, bạn có thể đặt khung thời gian trong 3 giây, và thậm chí sau đó nhấp vào 300 hoặc một nghìn lần, tối đa y sẽ nhận được trong 1 phút sẽ là 20 xu, nhấp 300 hoặc 1 triệu lần). Việc gỡ lỗi này phù hợp cho việc chống DDos, cho các chức năng như tìm kiếm trong đó mỗi thay đổi đối với onChange sẽ gây ra một truy vấn tới api của bạn. Debounce sẽ đợi người dùng ngừng nhập tên để thực hiện yêu cầu. Nếu nó được sử dụng trong kịch bản đồng xu được đề cập ở trên, người dùng sẽ chỉ giành được 1 đồng xu, bởi vì nó chỉ được thực thi, khi người dùng "tạm dừng" trong thời gian đã thiết lập. 453 +'interval' is different from the debouce. debouce if the user makes 1000 changes to a variable within 1 second, he will send only the last one after the stipulated timer (the default is 800 milliseconds). Interval will instead ignore all user actions for the stipulated period. If you send events for 1 minute, 1000 per second, debounce will only send you the last one, when the user stops strafing events. interval will deliver events every second, and if set to 3 seconds, it will deliver 20 events that minute. This is recommended to avoid abuse, in functions where the user can quickly click on something and get some advantage (imagine that the user can earn coins by clicking on something, if he clicked 300 times in the same minute, he would have 300 coins, using interval, you you can set a time frame for 3 seconds, and even then clicking 300 or a thousand times, the maximum he would get in 1 minute would be 20 coins, clicking 300 or 1 million times). The debounce is suitable for anti-DDos, for functions like search where each change to onChange would cause a query to your api. Debounce will wait for the user to stop typing the name, to make the request. If it were used in the coin scenario mentioned above, the user would only win 1 coin, because it is only executed, when the user "pauses" for the established time.
450 454
451 -* CHÍ Ú: Workers phải luôn được sử dụng khi khởi động Controller hoặc Class, vì vậy nó phải luôn ở trên onInit (được khuyến nghị), phương thức khởi tạo Class hoặc initState của StatefulWidget (phương pháp này không được khuyến khích trong hầu hết các trường hợp, nhưng nó không nên có hiệu ứng phụ nào khác). 455 +* NOTE: Workers should always be used when starting a Controller or Class, so it should always be on onInit (recommended), Class constructor, or the initState of a StatefulWidget (this practice is not recommended in most cases, but it shouldn't have any side effects).
452 456
453 -## Quản lý State đơn giản 457 +## Simple State Manager
454 458
455 -Get có một trình quản lý state cực kỳ nhẹ và dễ dàng, không sử dụng ChangeNotifier, sẽ đáp ứng nhu cầu đặc biệt cho những người mới sử dụng Flutter và sẽ không gây ra sự cố cho các ứng dụng lớn. 459 +Get has a state manager that is extremely light and easy, which does not use ChangeNotifier, will meet the need especially for those new to Flutter, and will not cause problems for large applications.
456 460
457 -GetBuilder nhắm chính xác vào việc kiểm soát nhiều state. Hãy tưởng tượng rằng bạn đã thêm 30 sản phẩm vào giỏ hàng, bạn nhấp vào xóa một sản phẩm, đồng thời danh sách được cập nhật, giá được cập nhật và huy hiệu trong giỏ hàng được cập nhật thành số lượng nhỏ hơn. Kiểu tiếp cận này khiến GetBuilder trở thành kẻ giết người, bởi vì nó nhóm các state và thay đổi tất cả chúng cùng một lúc mà không có bất kỳ "logic tính toán" nào cho điều đó. GetBuilder được tạo ra với loại tình huống này, vì để thay đổi state tạm thời, bạn có thể sử dụng setState và bạn sẽ không cần trình quản lý state cho việc này. 461 +GetBuilder is aimed precisely at multiple state control. Imagine that you added 30 products to a cart, you click delete one, at the same time that the list is updated, the price is updated and the badge in the shopping cart is updated to a smaller number. This type of approach makes GetBuilder killer, because it groups states and changes them all at once without any "computational logic" for that. GetBuilder was created with this type of situation in mind, since for ephemeral change of state, you can use setState and you would not need a state manager for this.
458 462
459 -Bằng cách đó, nếu bạn muốn một controller riêng lẻ, bạn có thể gán ID cho controller đó hoặc sử dụng GetX. Điều này là tùy thuộc vào bạn, hãy nhớ rằng bạn càng có nhiều widget "riêng lẻ" thì hiệu suất của GetX càng nổi bật, trong khi hiệu suất của GetBuilder phải vượt trội hơn khi có nhiều thay đổi state. 463 +That way, if you want an individual controller, you can assign IDs for that, or use GetX. This is up to you, remembering that the more "individual" widgets you have, the more the performance of GetX will stand out, while the performance of GetBuilder should be superior, when there is multiple change of state.
460 464
461 -### Lợi thế 465 +### Advantages
462 466
463 -1. Chỉ cập nhật các widget được yêu cầu. 467 +1. Update only the required widgets.
464 468
465 -2. Không sử dụng changeNotifier, đó là trình quản lý state sử dụng ít bộ nhớ hơn (gần như bằng 0mb). 469 +2. Does not use changeNotifier, it is the state manager that uses less memory (close to 0mb).
466 470
467 -3. Quên StatefulWidget! Với Get, bạn sẽ không bao giờ cần đến nó. Với các trình quản lý state khác, bạn có thể sẽ phải sử dụng StatefulWidget để lấy phiên bản của Provider, BLoC, MobX, v.v. Nhưng bạn đã bao giờ nghĩ rằng AppBar, Scaffole và hầu hết các widget trong class của bạn là stateless? Vậy tại sao phải lưu state của toàn bộ class, nếu bạn chỉ có thể lưu state của Widget là stateful? Get giải quyết được điều đó bằng cách tạo một class Stateless, làm cho mọi thứ trở nên vô trạng. Nếu bạn cần cập nhật một thành phần riêng lẻ, hãy bọc nó bằng GetBuilder và state của nó sẽ được duy trì. 471 +3. Forget StatefulWidget! With Get you will never need it. With the other state managers, you will probably have to use a StatefulWidget to get the instance of your Provider, BLoC, MobX Controller, etc. But have you ever stopped to think that your appBar, your scaffold, and most of the widgets that are in your class are stateless? So why save the state of an entire class, if you can only save the state of the Widget that is stateful? Get solves that, too. Create a Stateless class, make everything stateless. If you need to update a single component, wrap it with GetBuilder, and its state will be maintained.
468 472
469 -4. Tái cơ cấu cho dự án của bạn xanh, sạch và đẹp! Controller không được nằm trong UI của bạn, hãy đặt TextEditController của bạn hoặc bất kỳ controller nào bạn sử dụng trong class Controller của mình. 473 +4. Organize your project for real! Controllers must not be in your UI, place your TextEditController, or any controller you use within your Controller class.
470 474
471 -5. Bạn có cần kích hoạt event để cập nhật widget con ngay khi nó được hiển thị không? GetBuilder có thuộc tính "initState", giống như StatefulWidget và bạn có thể gọi các event từ controller của mình, trực tiếp từ nó, không có thêm event nào được đặt trong initState của bạn. 475 +5. Do you need to trigger an event to update a widget as soon as it is rendered? GetBuilder has the property "initState", just like StatefulWidget, and you can call events from your controller, directly from it, no more events being placed in your initState.
472 476
473 -6. Bạn có cần phải kích hoạt một hành động như đóng streams, hẹn giờ, v.v. không? GetBuilder cũng có dispose property, nơi bạn có thể gọi các event ngay khi widget đó bị phá hủy. 477 +6. Do you need to trigger an action like closing streams, timers and etc? GetBuilder also has the dispose property, where you can call events as soon as that widget is destroyed.
474 478
475 -7. Chỉ sử dụng các streams nếu cần thiết. Bạn có thể sử dụng StreamControllers bên trong controller của mình một cách bình thường và sử dụng StreamBuilder cũng bình thường, nhưng hãy nhớ rằng, một streams tiêu thụ bộ nhớ một kha khá, lập trình phản ứng rất đẹp, nhưng bạn không nên lạm dụng nó. 30 streams mở cùng lúc có thể tệ hơn changeNotifier (và changeNotifier đã rất là tệ). 479 +7. Use streams only if necessary. You can use your StreamControllers inside your controller normally, and use StreamBuilder also normally, but remember, a stream reasonably consumes memory, reactive programming is beautiful, but you shouldn't abuse it. 30 streams open simultaneously can be worse than changeNotifier (and changeNotifier is very bad).
476 480
477 -8. Cập nhật các widgets mà không tốn ram. Chỉ lưu trữ ID người tạo GetBuilder và cập nhật GetBuilder đó khi cần thiết. Mức tiêu thụ bộ nhớ của get ID trong bộ nhớ là rất thấp ngay cả đối với hàng nghìn GetBuilders. Khi bạn tạo GetBuilder mới, bạn thực sự đang chia sẻ state GetBuilder có ID người tạo. Một state mới không được tạo cho mỗi GetBuilder, giúp tiết kiệm RẤT NHIỀU ram cho các ứng dụng lớn. Về cơ bản, ứng dụng của bạn sẽ hoàn toàn là Không state và một số ít Tiện ích sẽ có state (trong GetBuilder) sẽ có một state duy nhất, và do đó cập nhật một sẽ cập nhật tất cả. Nhà nước chỉ là một. 481 +8. Update widgets without spending ram for that. Get stores only the GetBuilder creator ID, and updates that GetBuilder when necessary. The memory consumption of the get ID storage in memory is very low even for thousands of GetBuilders. When you create a new GetBuilder, you are actually sharing the state of GetBuilder that has a creator ID. A new state is not created for each GetBuilder, which saves A LOT OF ram for large applications. Basically your application will be entirely Stateless, and the few Widgets that will be Stateful (within GetBuilder) will have a single state, and therefore updating one will update them all. The state is just one.
478 482
479 -9. Get là toàn trí và trong hầu hết các trường hợp, nó biết chính xác thời gian để lấy controller ra khỏi bộ nhớ. Bạn không nên lo lắng về việc khi nào nên vứt bỏ controller, Get biết thời điểm tốt nhất để thực hiện việc này. 483 +9. Get is omniscient and in most cases it knows exactly the time to take a controller out of memory. You should not worry about when to dispose of a controller, Get knows the best time to do this.
480 484
481 -### Sử dụng 485 +### Usage
482 486
483 ``` dart 487 ``` dart
484 // Create controller class and extends GetxController 488 // Create controller class and extends GetxController
@@ -499,13 +503,13 @@ GetBuilder<Controller>( @@ -499,13 +503,13 @@ GetBuilder<Controller>(
499 //Initialize your controller only the first time. The second time you are using ReBuilder for the same controller, do not use it again. Your controller will be automatically removed from memory as soon as the widget that marked it as 'init' is deployed. You don't have to worry about that, Get will do it automatically, just make sure you don't start the same controller twice. 503 //Initialize your controller only the first time. The second time you are using ReBuilder for the same controller, do not use it again. Your controller will be automatically removed from memory as soon as the widget that marked it as 'init' is deployed. You don't have to worry about that, Get will do it automatically, just make sure you don't start the same controller twice.
500 ``` 504 ```
501 505
502 -**OK, giải thích xong rồi!** 506 +**Done!**
503 507
504 -* Bạn đã học cách quản lý state với Get. 508 +* You have already learned how to manage states with Get.
505 509
506 -* Lưu ý: Bạn có thể muốn một tổ chức lớn hơn và không sử dụng thuộc tính init. Vì vậy, bạn có thể tạo một class và mở rộng class Bindings và trong đó đề cập đến các controller sẽ được tạo trong route đó. Khi đó các Controllers sẽ không được tạo, ngược lại, đây chỉ là một câu lệnh, để lần đầu sử dụng Controller, Get sẽ biết cần tìm ở đâu. Get sẽ vẫn là lazyLoad và sẽ tiếp tục loại bỏ Controller khi chúng không còn cần thiết nữa. Hãy xem ví dụ pub.dev để xem nó hoạt động như thế nào. 510 +* Note: You may want a larger organization, and not use the init property. For that, you can create a class and extends Bindings class, and within it mention the controllers that will be created within that route. Controllers will not be created at that time, on the contrary, this is just a statement, so that the first time you use a Controller, Get will know where to look. Get will remain lazyLoad, and will continue to dispose Controllers when they are no longer needed. See the pub.dev example to see how it works.
507 511
508 -Nếu bạn điều hướng nhiều route và cần dữ liệu trong controller đã sử dụng trước đó, bạn chỉ cần sử dụng GetBuilder Again (không có init): 512 +If you navigate many routes and need data that was in your previously used controller, you just need to use GetBuilder Again (with no init):
509 513
510 ``` dart 514 ``` dart
511 class OtherClass extends StatelessWidget { 515 class OtherClass extends StatelessWidget {
@@ -522,7 +526,7 @@ class OtherClass extends StatelessWidget { @@ -522,7 +526,7 @@ class OtherClass extends StatelessWidget {
522 526
523 ``` 527 ```
524 528
525 -Nếu bạn cần sử dụng controller của mình ở nhiều nơi khác và bên ngoài GetBuilder, chỉ cần tạo quyền truy cập vào controller của bạn và có nó một cách dễ dàng. (hoặc sử dụng `Get.find <Controller> ()`) 529 +If you need to use your controller in many other places, and outside of GetBuilder, just create a get in your controller and have it easily. (or use `Get.find<Controller>()` )
526 530
527 ``` dart 531 ``` dart
528 class Controller extends GetxController { 532 class Controller extends GetxController {
@@ -541,7 +545,7 @@ class Controller extends GetxController { @@ -541,7 +545,7 @@ class Controller extends GetxController {
541 } 545 }
542 ``` 546 ```
543 547
544 -Sau đó, truy cập thẳng vào controller của bạn: 548 +And then you can access your controller directly, that way:
545 549
546 ``` dart 550 ``` dart
547 FloatingActionButton( 551 FloatingActionButton(
@@ -552,24 +556,24 @@ FloatingActionButton( @@ -552,24 +556,24 @@ FloatingActionButton(
552 ), 556 ),
553 ``` 557 ```
554 558
555 -Khi bạn nhấn FloatingActionButton, tất cả các widget đang lắng nghe biến 'counter' sẽ được cập nhật tự động. 559 +When you press FloatingActionButton, all widgets that are listening to the 'counter' variable will be updated automatically.
556 560
557 -### Cách GetX sử dụng controllers 561 +### How it handles controllers
558 562
559 -Ví dụ: 563 +Let's say we have this:
560 564
561 `Class a => Class B (has controller X) => Class C (has controller X)` 565 `Class a => Class B (has controller X) => Class C (has controller X)`
562 566
563 -Trong class A, controller chưa có trong bộ nhớ, vì bạn chưa sử dụng nó (Get là lazyLoad). Trong class B, bạn đã sử dụng controller và nó đã vào bộ nhớ. Trong class C, bạn đã sử dụng cùng một controller như trong class B, Get sẽ chia sẻ state của controller B với controller C, và controller tương tự vẫn còn trong bộ nhớ. Nếu bạn đóng màn hình C và màn hình B, Get sẽ tự động lấy controller X ra khỏi bộ nhớ và giải phóng tài nguyên, vì Class A không sử dụng controller. Nếu bạn điều hướng đến B một lần nữa, controller X sẽ nhập lại bộ nhớ, nếu thay vì đi đến class C, bạn quay lại class A một lần nữa, Get sẽ đưa controller ra khỏi bộ nhớ theo cách tương tự. Nếu class C không sử dụng controller và bạn đã lấy class B ra khỏi bộ nhớ, thì sẽ không có class nào sử dụng controller X và tương tự như vậy, nó sẽ bị loại bỏ. Ngoại lệ duy nhất có thể gây rắc rối với Get là nếu bạn xóa B khỏi route một cách bất ngờ và cố gắng sử dụng controller trong C. Trong trường hợp này, ID người tạo của controller ở B đã bị xóa và Get được lập trình để xóa nó khỏi bộ nhớ mọi controller không có ID người tạo. Nếu bạn dự định làm điều này, hãy thêm flag "autoRemove: false" vào GetBuilder của class B và sử dụng adoptID = true trong GetBuilder của class C. 567 +In class A the controller is not yet in memory, because you have not used it yet (Get is lazyLoad). In class B you used the controller, and it entered memory. In class C you used the same controller as in class B, Get will share the state of controller B with controller C, and the same controller is still in memory. If you close screen C and screen B, Get will automatically take controller X out of memory and free up resources, because Class a is not using the controller. If you navigate to B again, controller X will enter memory again, if instead of going to class C, you return to class A again, Get will take the controller out of memory in the same way. If class C didn't use the controller, and you took class B out of memory, no class would be using controller X and likewise it would be disposed of. The only exception that can mess with Get, is if you remove B from the route unexpectedly, and try to use the controller in C. In this case, the creator ID of the controller that was in B was deleted, and Get was programmed to remove it from memory every controller that has no creator ID. If you intend to do this, add the "autoRemove: false" flag to class B's GetBuilder and use adoptID = true; in class C's GetBuilder.
564 568
565 -### Không cần StatefulWidget nữa! 569 +### You won't need StatefulWidgets anymore
566 570
567 -Sử dụng StatefulWidgets có nghĩa là lưu trữ state của toàn bộ màn hình một cách không cần thiết, ngay cả khi bạn cần xây dựng lại một cách tối thiểu widget, bạn sẽ nhúng nó vào Consumer / Observer / BlocProvider / GetBuilder / GetX / Obx, đây sẽ là một StatefulWidget khác.  
568 -Class StatefulWidget là một class lớn hơn StatelessWidget, class này sẽ phân bổ nhiều RAM hơn và điều này có thể không tạo ra sự khác biệt đáng kể giữa một hoặc hai class, nhưng chắc chắn nó sẽ làm được khi bạn có 100 class trong số chúng!  
569 -Trừ khi bạn cần sử dụng một mixin, như TickerProviderStateMixin, thì việc sử dụng StatefulWidget với Get là hoàn toàn không cần thiết. 571 +Using StatefulWidgets means storing the state of entire screens unnecessarily, even because if you need to minimally rebuild a widget, you will embed it in a Consumer/Observer/BlocProvider/GetBuilder/GetX/Obx, which will be another StatefulWidget.
  572 +The StatefulWidget class is a class larger than StatelessWidget, which will allocate more RAM, and this may not make a significant difference between one or two classes, but it will most certainly do when you have 100 of them!
  573 +Unless you need to use a mixin, like TickerProviderStateMixin, it will be totally unnecessary to use a StatefulWidget with Get.
570 574
571 -Bạn có thể gọi trực tiếp tất cả các phương thức của StatefulWidget từ GetBuilder.  
572 -Nếu bạn cần gọi phương thức initState () hoặc dispose () chẳng hạn, bạn có thể gọi chúng trực tiếp; 575 +You can call all methods of a StatefulWidget directly from a GetBuilder.
  576 +If you need to call initState() or dispose() method for example, you can call them directly;
573 577
574 ``` dart 578 ``` dart
575 GetBuilder<Controller>( 579 GetBuilder<Controller>(
@@ -579,7 +583,7 @@ GetBuilder<Controller>( @@ -579,7 +583,7 @@ GetBuilder<Controller>(
579 ), 583 ),
580 ``` 584 ```
581 585
582 -Một cách tiếp cận tốt hơn nhiều so với cách này là sử dụng phương thức onInit () và onClose () trực tiếp từ controller của bạn. 586 +A much better approach than this is to use the onInit() and onClose() method directly from your controller.
583 587
584 ``` dart 588 ``` dart
585 @override 589 @override
@@ -589,17 +593,17 @@ void onInit() { @@ -589,17 +593,17 @@ void onInit() {
589 } 593 }
590 ``` 594 ```
591 595
592 -* CHÍ Ú: Nếu bạn muốn bắt đầu một phương thức tại thời điểm controller được gọi lần đầu tiên, bạn KHÔNG CẦN sử dụng các hàm tạo cho việc này, trên thực tế, bằng cách sử dụng gói hướng hiệu suất như Get, điều này không phù hợp với thực tiễn xấu, bởi vì nó lệch khỏi logic trong đó controller được tạo hoặc chỉ định (nếu bạn tạo một phiên bản của controller này, hàm tạo sẽ được gọi ngay lập tức, bạn sẽ điền controller trước khi nó được sử dụng, bạn đang cấp phát bộ nhớ mà không sử dụng nó , điều này chắc chắn làm hỏng các nguyên tắc của thư viện này). Các phương thức onInit(); và onClose(); được tạo ra cho mục đích này, chúng sẽ được gọi khi Controller được tạo hoặc được sử dụng lần đầu tiên, tùy thuộc vào việc bạn có đang sử dụng Get.lazyPut hay không. Ví dụ: nếu bạn muốn thực hiện lệnh gọi tới API của mình để điền dữ liệu, bạn có thể quên phương thức cũ của initState / dispose, chỉ cần bắt đầu lệnh gọi tới api trong onInit. Nếu bạn cần thực thi bất kỳ lệnh nào, như đóng streams, hãy sử dụng onClose() cho việc đó. 596 +* NOTE: If you want to start a method at the moment the controller is called for the first time, you DON'T NEED to use constructors for this, in fact, using a performance-oriented package like Get, this borders on bad practice, because it deviates from the logic in which the controllers are created or allocated (if you create an instance of this controller, the constructor will be called immediately, you will be populating a controller before it is even used, you are allocating memory without it being in use, this definitely hurts the principles of this library). The onInit() methods; and onClose(); were created for this, they will be called when the Controller is created, or used for the first time, depending on whether you are using Get.lazyPut or not. If you want, for example, to make a call to your API to populate data, you can forget about the old-fashioned method of initState/dispose, just start your call to the api in onInit, and if you need to execute any command like closing streams, use the onClose() for that.
593 597
594 -### Tại sao GetX tồn tại? 598 +### Why it exists
595 599
596 -Mục đích của gói này chính xác là cung cấp cho bạn một giải pháp hoàn chỉnh để điều hướng các route, quản lý các dependency và state, sử dụng các dependency ít nhất có thể, với mức độ tách biệt cao. Nhận tất cả các API Flutter cấp cao và cấp thấp trong chính nó, để đảm bảo rằng bạn làm việc với ít khớp nối nhất có thể. Chúng tôi tập trung mọi thứ trong một gói duy nhất, để đảm bảo rằng bạn không có bất kỳ loại khớp nối nào trong dự án của mình. Bằng cách đó, bạn có thể chỉ đặt các widget trong chế độ xem của mình và để phần của nhóm làm việc với logic nghiệp vụ tự do làm việc với logic nghiệp vụ độc lập với View. Điều này cung cấp một môi trường làm việc sạch hơn nhiều, để một phần nhóm của bạn chỉ hoạt động với các widget mà không phải lo lắng về việc gửi dữ liệu đến controller của bạn và một phần nhóm của bạn chỉ làm việc với logic nghiệp vụ trong phạm vi bề rộng của nó mà không dependency vào bất kỳ yếu tố View. 600 +The purpose of this package is precisely to give you a complete solution for navigation of routes, management of dependencies and states, using the least possible dependencies, with a high degree of decoupling. Get engages all high and low level Flutter APIs within itself, to ensure that you work with the least possible coupling. We centralize everything in a single package, to ensure that you don't have any kind of coupling in your project. That way, you can put only widgets in your view, and leave the part of your team that works with the business logic free, to work with the business logic without depending on any element of the View. This provides a much cleaner working environment, so that part of your team works only with widgets, without worrying about sending data to your controller, and part of your team works only with the business logic in its breadth, without depending on no element of the view.
597 601
598 -Vì vậy, để đơn giản hóa điều này:  
599 -Bạn không cần gọi các phương thức trong initState và gửi chúng theo tham số đến controller của mình, cũng như không sử dụng phương thức khởi tạo controller cho việc đó, bạn có phương thức onInit() được gọi vào đúng thời điểm để bạn khởi động các dịch vụ của mình.  
600 -Bạn không cần phải gọi thiết bị, bạn có phương thức onClose() sẽ được gọi vào thời điểm chính xác khi controller của bạn không còn cần thiết nữa và sẽ bị xóa khỏi bộ nhớ. Bằng cách đó, chỉ để lại chế độ xem cho các widget, tránh bất kỳ loại logic nghiệp vụ nào từ nó. 602 +So to simplify this:
  603 +You don't need to call methods in initState and send them by parameter to your controller, nor use your controller constructor for that, you have the onInit() method that is called at the right time for you to start your services.
  604 +You do not need to call the device, you have the onClose() method that will be called at the exact moment when your controller is no longer needed and will be removed from memory. That way, leave views for widgets only, refrain from any kind of business logic from it.
601 605
602 -Đừng gọi một phương thức vứt bỏ bên trong GetxController, nó sẽ không làm được gì cả, hãy nhớ rằng controller không phải là một Widget, bạn không nên "vứt bỏ" nó, và nó sẽ được Get tự động và thông minh xóa khỏi bộ nhớ. Nếu bạn đã sử dụng bất kỳ streams nào trên đó và muốn đóng streams đó, chỉ cần chèn streams đó vào phương thức đóng. Thí dụ: 606 +Do not call a dispose method inside GetxController, it will not do anything, remember that the controller is not a Widget, you should not "dispose" it, and it will be automatically and intelligently removed from memory by Get. If you used any stream on it and want to close it, just insert it into the close method. Example:
603 607
604 ``` dart 608 ``` dart
605 class Controller extends GetxController { 609 class Controller extends GetxController {
@@ -616,15 +620,15 @@ class Controller extends GetxController { @@ -616,15 +620,15 @@ class Controller extends GetxController {
616 } 620 }
617 ``` 621 ```
618 622
619 -Vòng đời của controller: 623 +Controller life cycle:
620 624
621 -* onInit() nơi nó được tạo.  
622 -* onClose() nơi nó được đóng để thực hiện bất kỳ thay đổi nào nhằm chuẩn bị cho phương thức xóa  
623 -* deleted: bạn không có quyền truy cập vào API này vì nó sẽ xóa controller khỏi bộ nhớ theo đúng nghĩa đen. Nó được xóa theo đúng nghĩa đen, mà không để lại bất kỳ dấu vết nào. 625 +* onInit() where it is created.
  626 +* onClose() where it is closed to make any changes in preparation for the delete method
  627 +* deleted: you do not have access to this API because it is literally removing the controller from memory. It is literally deleted, without leaving any trace.
624 628
625 -### Cách sử dụng khác 629 +### Other ways of using it
626 630
627 -Bạn có thể sử dụng phiên bản Controller trực tiếp trên giá trị GetBuilder: 631 +You can use Controller instance directly on GetBuilder value:
628 632
629 ``` dart 633 ``` dart
630 GetBuilder<Controller>( 634 GetBuilder<Controller>(
@@ -635,7 +639,7 @@ GetBuilder<Controller>( @@ -635,7 +639,7 @@ GetBuilder<Controller>(
635 ), 639 ),
636 ``` 640 ```
637 641
638 -Bạn cũng có thể cần một phiên bản của controller bên ngoài GetBuilder và bạn có thể sử dụng các phương pháp này để đạt được điều này: 642 +You may also need an instance of your controller outside of your GetBuilder, and you can use these approaches to achieve this:
639 643
640 ``` dart 644 ``` dart
641 class Controller extends GetxController { 645 class Controller extends GetxController {
@@ -667,7 +671,7 @@ GetBuilder<Controller>( @@ -667,7 +671,7 @@ GetBuilder<Controller>(
667 ), 671 ),
668 ``` 672 ```
669 673
670 -* Bạn có thể sử dụng các phương pháp tiếp cận "không chuẩn" để thực hiện việc này. Nếu bạn đang sử dụng một số trình quản lý dependency khác, như get_it, modular, v.v. và chỉ muốn cung cấp phiên bản controller, bạn có thể thực hiện điều này: 674 +* You can use "non-canonical" approaches to do this. If you are using some other dependency manager, like get_it, modular, etc., and just want to deliver the controller instance, you can do this:
671 675
672 ``` dart 676 ``` dart
673 Controller controller = Controller(); 677 Controller controller = Controller();
@@ -681,9 +685,9 @@ GetBuilder<Controller>( @@ -681,9 +685,9 @@ GetBuilder<Controller>(
681 685
682 ``` 686 ```
683 687
684 -### IDs độc nhất 688 +### Unique IDs
685 689
686 -Nếu bạn muốn tinh chỉnh kiểm soát cập nhật của widget con với GetBuilder, bạn có thể gán cho chúng các ID độc: 690 +If you want to refine a widget's update control with GetBuilder, you can assign them unique IDs:
687 691
688 ``` dart 692 ``` dart
689 GetBuilder<Controller>( 693 GetBuilder<Controller>(
@@ -695,43 +699,44 @@ GetBuilder<Controller>( @@ -695,43 +699,44 @@ GetBuilder<Controller>(
695 ), 699 ),
696 ``` 700 ```
697 701
698 -Và cập nhật nó vào biểu mẫu này: 702 +And update it this form:
699 703
700 ``` dart 704 ``` dart
701 update(['text']); 705 update(['text']);
702 ``` 706 ```
703 707
704 -Bạn cũng có thể áp đặt các điều kiện cho bản cập nhật: 708 +You can also impose conditions for the update:
705 709
706 ``` dart 710 ``` dart
707 update(['text'], counter < 10); 711 update(['text'], counter < 10);
708 ``` 712 ```
709 713
710 -GetX thực hiện điều này tự động và chỉ cấu trúc lại widget con sử dụng biến chính xác đã được thay đổi, nếu bạn thay đổi một biến thành giống với biến trước đó và điều đó không ngụ ý thay đổi state, GetX sẽ không xây dựng lại widget con để tiết kiệm bộ nhớ và Chu kỳ CPU ( 3 đang được hiển thị trên màn hình và bạn lại thay đổi biến thành 3. Trong hầu hết các trình quản lý state, điều này sẽ gây ra việc xây dựng lại mới, nhưng với GetX, widget sẽ chỉ được xây dựng lại, nếu trên thực tế state của nó đã thay đổi ). 714 +GetX does this automatically and only reconstructs the widget that uses the exact variable that was changed, if you change a variable to the same as the previous one and that does not imply a change of state , GetX will not rebuild the widget to save memory and CPU cycles (3 is being displayed on the screen, and you change the variable to 3 again. In most state managers, this will cause a new rebuild, but with GetX the widget will only is rebuilt again, if in fact his state has changed).
711 715
712 -## Trộn hai trình quản lý state 716 +## Mixing the two state managers
713 717
714 -Một số người đã mở một yêu cầu tính năng, vì họ chỉ muốn sử dụng một loại biến phản ứng và cơ chế khác và cần chèn Obx vào GetBuilder cho việc này. Suy nghĩ về nó MixinBuilder đã được tạo ra. Nó cho phép cả những thay đổi phản ứng bằng cách thay đổi các biến ".obs" và cập nhật thủ công thông qua update(). Tuy nhiên, trong số 4 widget, nó là widget tiêu tốn nhiều tài nguyên nhất, vì ngoài việc có Subscription để nhận các event thay đổi từ con mình, nó còn đăng ký phương thức cập nhật của controller của mình. 718 +Some people opened a feature request, as they wanted to use only one type of reactive variable, and the other mechanics, and needed to insert an Obx into a GetBuilder for this. Thinking about it MixinBuilder was created. It allows both reactive changes by changing ".obs" variables, and mechanical updates via update(). However, of the 4 widgets he is the one that consumes the most resources, since in addition to having a Subscription to receive change events from his children, he subscribes to the update method of his controller.
715 719
716 -Việc mở rộng GetxController rất quan trọng, vì chúng có vòng đời và có thể "bắt đầu" và "kết thúc" các event trong các phương thức onInit() và onClose() của chúng. Bạn có thể sử dụng bất kỳ lớp nào cho việc này, nhưng tôi thực sự khuyên bạn nên sử dụng lớp GetxController để đặt các biến của bạn, cho dù chúng có thể quan sát được hay không. 720 +Extending GetxController is important, as they have life cycles, and can "start" and "end" events in their onInit() and onClose() methods. You can use any class for this, but I strongly recommend you use the GetxController class to place your variables, whether they are observable or not.
717 721
718 ## StateMixin 722 ## StateMixin
719 723
720 -Một cách khác để xử lý state `UI` của bạn là sử dụng` StateMixin <T> `.  
721 -Để triển khai nó, hãy sử dụng dấu `với` để thêm` StateMixin <T> ` bộ điều khiển của bạn cho phép một mô hình T. 724 +Another way to handle your `UI` state is use the `StateMixin<T>` .
  725 +To implement it, use the `with` to add the `StateMixin<T>`
  726 +to your controller which allows a T model.
722 727
723 ``` dart 728 ``` dart
724 class Controller extends GetController with StateMixin<User>{} 729 class Controller extends GetController with StateMixin<User>{}
725 ``` 730 ```
726 731
727 -Phương thức `change()` thay đổi state bất cứ khi nào chúng ta muốn.  
728 -Chỉ cần truyền dữ liệu và state theo cách này: 732 +The `change()` method change the State whenever we want.
  733 +Just pass the data and the status in this way:
729 734
730 ```dart 735 ```dart
731 change(data, status: RxStatus.success()); 736 change(data, status: RxStatus.success());
732 ``` 737 ```
733 738
734 -RxStatus cho phép các state này: 739 +RxStatus allow these status:
735 740
736 ``` dart 741 ``` dart
737 RxStatus.loading(); 742 RxStatus.loading();
@@ -740,7 +745,7 @@ RxStatus.empty(); @@ -740,7 +745,7 @@ RxStatus.empty();
740 RxStatus.error('message'); 745 RxStatus.error('message');
741 ``` 746 ```
742 747
743 -Để diễn tả nó trên UI, sử dụng: 748 +To represent it in the UI, use:
744 749
745 ```dart 750 ```dart
746 class OtherClass extends GetView<Controller> { 751 class OtherClass extends GetView<Controller> {
@@ -766,19 +771,19 @@ class OtherClass extends GetView<Controller> { @@ -766,19 +771,19 @@ class OtherClass extends GetView<Controller> {
766 771
767 ## GetBuilder vs GetX vs Obx vs MixinBuilder 772 ## GetBuilder vs GetX vs Obx vs MixinBuilder
768 773
769 -Trong một thập kỷ làm việc với lập trình, tôi đã có thể học được một số bài học quý giá. 774 +In a decade working with programming I was able to learn some valuable lessons.
770 775
771 -Lần đầu tiên tôi tiếp xúc với lập trình phản ứng là rất "Trời thần ơi, tuyệt vời ông mặt trời!" và trên thực tế, lập trình phản ứng là không thể tin được.  
772 -Tuy nhiên, nó không phải là thích hợp cho tất cả các trường hợp. Thông thường, tất cả những gì bạn cần là thay đổi state của 2 hoặc 3 widget cùng lúc, hoặc thay đổi state trong thời gian ngắn, trong trường hợp này, lập trình phản ứng không phải là xấu, nhưng nó không phù hợp. 776 +My first contact with reactive programming was so "wow, this is incredible" and in fact reactive programming is incredible.
  777 +However, it is not suitable for all situations. Often all you need is to change the state of 2 or 3 widgets at the same time, or an ephemeral change of state, in which case reactive programming is not bad, but it is not appropriate.
773 778
774 -Lập trình phản ứng có mức tiêu thụ RAM cao hơn có thể được bù đắp bởi quy trình làm việc riêng lẻ, điều này sẽ đảm bảo rằng chỉ một widget con được xây dựng lại và khi cần thiết, nhưng tạo danh sách với 80 đối tượng, mỗi đối tượng có nhiều streams không phải là một ý kiến hay . Mở thanh kiểm tra phi tiêu và kiểm tra xem StreamBuilder tiêu thụ bao nhiêu và bạn sẽ hiểu những gì tôi đang cố gắng nói với bạn. 779 +Reactive programming has a higher consumption of RAM consumption that can be compensated for by the individual workflow, which will ensure that only one widget is rebuilt and when necessary, but creating a list with 80 objects, each with several streams is not a good one idea. Open the dart inspect and check how much a StreamBuilder consumes, and you'll understand what I'm trying to tell you.
775 780
776 -Với ý nghĩ đó, tôi đã tạo trình quản lý state đơn giản. Nó đơn giản, và đó chính xác là những gì bạn cần ở nó: cập nhật state trong các khối theo cách đơn giản và tiết kiệm nhất. 781 +With that in mind, I created the simple state manager. It is simple, and that is exactly what you should demand from it: updating state in blocks in a simple way, and in the most economical way.
777 782
778 -GetBuilder rất tiết kiệm RAM và khó có cách tiếp cận nào tiết kiệm hơn nó (ít nhất là tôi không thể tưởng tượng được, nếu đã tồn tại cách khác, vui lòng cho chúng tôi biết). 783 +GetBuilder is very economical in RAM, and there is hardly a more economical approach than him (at least I can't imagine one, if it exists, please let us know).
779 784
780 -Tuy nhiên, GetBuilder vẫn là một trình quản lý state cơ học, bạn cần phải gọi update () giống như bạn sẽ cần gọi tới Provider's InformListaries (). 785 +However, GetBuilder is still a mechanical state manager, you need to call update() just like you would need to call Provider's notifyListeners().
781 786
782 -Có những tình huống khác mà lập trình phản ứng thực sự thú vị và nếu không dùng nó đồng nghĩa như đang phát minh lại cái bánh xe. Với suy nghĩ đó, GetX được tạo ra để cung cấp mọi thứ hiện đại và tiên tiến nhất trong một trình quản lý state. Nó chỉ cập nhật những gì cần thiết và khi cần thiết, nếu bạn gặp lỗi và gửi 300 state thay đổi đồng thời, GetX sẽ lọc và cập nhật màn hình chỉ khi state thực sự thay đổi. 787 +There are other situations where reactive programming is really interesting, and not working with it is the same as reinventing the wheel. With that in mind, GetX was created to provide everything that is most modern and advanced in a state manager. It updates only what is necessary and when necessary, if you have an error and send 300 state changes simultaneously, GetX will filter and update the screen only if the state actually changes.
783 788
784 -GetX vẫn tiết kiệm hơn bất kỳ trình quản lý state phản ứng nào khác, nhưng nó tiêu tốn nhiều RAM hơn GetBuilder một chút. Suy nghĩ về điều đó và hướng tới việc tiêu thụ tối đa tài nguyên mà Obx đã tạo ra. Không giống như GetX và GetBuilder, bạn sẽ không thể khởi tạo controller bên trong Obx, nó chỉ là một Widget với StreamSubscription nhận các event thay đổi từ con bạn, vậy thôi. Nó tiết kiệm hơn GetX, nhưng thua GetBuilder, điều được mong đợi, vì nó có tính phản ứng và GetBuilder có cách tiếp cận đơn giản nhất tồn tại, đó là lưu trữ hashCode của widget con và StateSetter của nó. Với Obx, bạn không cần phải viết loại controller của mình và bạn có thể nghe thấy sự thay đổi từ nhiều controller khác nhau, nhưng nó cần được khởi tạo trước đó, sử dụng phương pháp ví dụ ở đầu readme này hoặc sử dụng class Bindings. 789 +GetX is still more economical than any other reactive state manager, but it consumes a little more RAM than GetBuilder. Thinking about it and aiming to maximize the consumption of resources that Obx was created. Unlike GetX and GetBuilder, you will not be able to initialize a controller inside an Obx, it is just a Widget with a StreamSubscription that receives change events from your children, that's all. It is more economical than GetX, but loses to GetBuilder, which was to be expected, since it is reactive, and GetBuilder has the most simplistic approach that exists, of storing a widget's hashcode and its StateSetter. With Obx you don't need to write your controller type, and you can hear the change from multiple different controllers, but it needs to be initialized before, either using the example approach at the beginning of this readme, or using the Bindings class.
  1 +# Quản lý dependency
  2 +- [Quản lý dependency](#dependency-management)
  3 + - [Instancing methods](#instancing-methods)
  4 + - [Get.put()](#getput)
  5 + - [Get.lazyPut](#getlazyput)
  6 + - [Get.putAsync](#getputasync)
  7 + - [Get.create](#getcreate)
  8 + - [Sử dụng các phương thức / class](#using-instantiated-methodsclasses)
  9 + - [Khác nhau giữa phương thức (methods)](#differences-between-methods)
  10 + - [Bindings](#bindings)
  11 + - [Cách sử dụng](#how-to-use)
  12 + - [BindingsBuilder](#bindingsbuilder)
  13 + - [SmartManagement](#smartmanagement)
  14 + - [Cách thay đổi](#How-to-change)
  15 + - [SmartManagement.full](#smartmanagementfull)
  16 + - [SmartManagement.onlyBuilders](#smartmanagementonlybuilders)
  17 + - [SmartManagement.keepFactory](#smartmanagementkeepfactory)
  18 + - [Cách bindings làm việc ngầm](#how-bindings-work-under-the-hood)
  19 + - [Chí ú](#notes)
  20 +
  21 +Get có một trình quản lý dependency đơn giản và mạnh mẽ cho phép bạn truy xuất cùng một class với Blocs hoặc Controller của bạn chỉ với 1 dòng mã, không có "context", không có InheritedWidget
  22 +
  23 +```dart
  24 +Controller controller = Get.put(Controller()); // Rather Controller controller = Controller();
  25 +```
  26 +
  27 +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.
  28 +Vì vậy, bạn có thể sử dụng controller (hoặc class Blocs) của mình một cách bình thường
  29 +
  30 +- Note: Nếu bạn đang sử dụng Get's State Manager, hãy chú ý hơn đến [Bindings](#bindings) api, điều này sẽ giúp kết nối chế độ xem với controller của bạn dễ dàng hơn.
  31 +- Note²: Quản lý state của Get được tách biệt khỏi các phần khác của gói, vì vậy, nếu ví dụ: nếu ứng dụng của bạn đã sử dụng trình quản lý state (bất kỳ cái nào, không quan trọng), bạn không cần phải thay đổi điều đó, bạn có thể sử dụng phần dependency này người quản lý không có vấn đề gì cả
  32 +
  33 +## Instancing methods
  34 +Các phương thức và các tham số có thể định cấu hình của nó là:
  35 +
  36 +### Get.put()
  37 +
  38 +Cách phổ biến nhất để chèn một dependency, là một điều tốt cho controller của View của bạn.
  39 +
  40 +```dart
  41 +Get.put<SomeClass>(SomeClass());
  42 +Get.put<LoginController>(LoginController(), permanent: true);
  43 +Get.put<ListItemController>(ListItemController, tag: "some unique string");
  44 +```
  45 +
  46 +Đây là tùy chọn mà bạn có thể đặt lệnh:
  47 +```dart
  48 +Get.put<S>(
  49 + // mandatory: the class that you want to get to save, like a controller or anything
  50 + // note: "S" means that it can be a class of any type
  51 + S dependency
  52 +
  53 + // optional: this is for when you want multiple classess that are of the same type
  54 + // since you normally get a class by using Get.find<Controller>(),
  55 + // you need to use tag to tell which instance you need
  56 + // must be unique string
  57 + String tag,
  58 +
  59 + // optional: by default, get will dispose instances after they are not used anymore (example,
  60 + // the controller of a view that is closed), but you might need that the instance
  61 + // to be kept there throughout the entire app, like an instance of sharedPreferences or something
  62 + // so you use this
  63 + // defaults to false
  64 + bool permanent = false,
  65 +
  66 + // optional: allows you after using an abstract class in a test, replace it with another one and follow the test.
  67 + // defaults to false
  68 + bool overrideAbstract = false,
  69 +
  70 + // optional: allows you to create the dependency using function instead of the dependency itself.
  71 + // this one is not commonly used
  72 + InstanceBuilderCallback<S> builder,
  73 +)
  74 +```
  75 +
  76 +### Get.lazyPut
  77 +Có thể lazyLoad một dependecy để nó chỉ được khởi tạo khi được sử dụng. Rất hữu ích cho các class ngốn nhiều tài nguyên hoặc nếu bạn muốn khởi tạo một số class chỉ ở một nơi (như trong class Bindings) và bạn biết rằng mình sẽ không sử dụng class đó tại thời điểm nhất định.
  78 +
  79 +```dart
  80 +/// ApiMock will only be called when someone uses Get.find<ApiMock> for the first time
  81 +Get.lazyPut<ApiMock>(() => ApiMock());
  82 +
  83 +Get.lazyPut<FirebaseAuth>(
  84 + () {
  85 + // ... some logic if needed
  86 + return FirebaseAuth();
  87 + },
  88 + tag: Math.random().toString(),
  89 + fenix: true
  90 +)
  91 +
  92 +Get.lazyPut<Controller>( () => Controller() )
  93 +```
  94 +
  95 +Đây là các tùy chọn bạn có thể đặt lệnh:
  96 +```dart
  97 +Get.lazyPut<S>(
  98 + // mandatory: a method that will be executed when your class is called for the first time
  99 + InstanceBuilderCallback builder,
  100 +
  101 + // optional: same as Get.put(), it is used for when you want multiple different instance of a same class
  102 + // must be unique
  103 + String tag,
  104 +
  105 + // optional: It is similar to "permanent", the difference is that the instance is discarded when
  106 + // is not being used, but when it's use is needed again, Get will recreate the instance
  107 + // just the same as "SmartManagement.keepFactory" in the bindings api
  108 + // defaults to false
  109 + bool fenix = false
  110 +
  111 +)
  112 +```
  113 +
  114 +### Get.putAsync
  115 + Đây là khi bạn muốn xài asynchronize code `Get.putAsync`:
  116 +
  117 +```dart
  118 +Get.putAsync<SharedPreferences>(() async {
  119 + final prefs = await SharedPreferences.getInstance();
  120 + await prefs.setInt('counter', 12345);
  121 + return prefs;
  122 +});
  123 +
  124 +Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() )
  125 +```
  126 +
  127 +Đây là tùy chọn bạn có thể đặt lệnh với putAsync:
  128 +```dart
  129 +Get.putAsync<S>(
  130 +
  131 + // mandatory: an async method that will be executed to instantiate your class
  132 + AsyncInstanceBuilderCallback<S> builder,
  133 +
  134 + // optional: same as Get.put(), it is used for when you want multiple different instance of a same class
  135 + // must be unique
  136 + String tag,
  137 +
  138 + // optional: same as in Get.put(), used when you need to maintain that instance alive in the entire app
  139 + // defaults to false
  140 + bool permanent = false
  141 +)
  142 +```
  143 +
  144 +### Get.create
  145 +
  146 +Cái này hơi khó giải thích, nhưng sự khác nhau giữa chúng có thể được tìm thấy trên mục [Differences between methods:](#differences-between-methods)
  147 +
  148 +```dart
  149 +Get.Create<SomeClass>(() => SomeClass());
  150 +Get.Create<LoginController>(() => LoginController());
  151 +```
  152 +
  153 +Tùy chọn có thể sử dụng:
  154 +
  155 +```dart
  156 +Get.create<S>(
  157 + // required: a function that returns a class that will be "fabricated" every
  158 + // time `Get.find()` is called
  159 + // Example: Get.create<YourClass>(() => YourClass())
  160 + FcBuilderFunc<S> builder,
  161 +
  162 + // optional: just like Get.put(), but it is used when you need multiple instances
  163 + // of a of a same class
  164 + // Useful in case you have a list that each item need it's own controller
  165 + // needs to be a unique string. Just change from tag to name
  166 + String name,
  167 +
  168 + // optional: just like int`Get.put()`, it is for when you need to keep the
  169 + // instance alive thoughout the entire app. The difference is in Get.create
  170 + // permanent is true by default
  171 + bool permanent = true
  172 +```
  173 +
  174 +## Sử dụng các phương thức / class
  175 +
  176 +Hãy tưởng tượng rằng bạn đã điều hướng qua nhiều route và bạn cần một dữ liệu còn sót trong controller của mình, bạn sẽ cần một trình quản lý state kết hợp với Provider hoặc Get_it, phải hem? Với Get, bạn chỉ cần yêu cầu Get to "find" cho controller của mình và thế là xong:
  177 +
  178 +```dart
  179 +final controller = Get.find<Controller>();
  180 +// OR
  181 +Controller controller = Get.find();
  182 +
  183 +// Yes, it looks like Magic, Get will find your controller, and will deliver it to you.
  184 +// You can have 1 million controllers instantiated, Get will always give you the right controller.
  185 +```
  186 +
  187 +Và sau đó, bạn sẽ có thể khôi phục dữ liệu controller của mình đã lấy được ở đó:
  188 +
  189 +```dart
  190 +Text(controller.textFromApi);
  191 +```
  192 +
  193 +Vì giá trị trả về là một class bình thường, bạn có thể làm bất cứ điều gì bạn muốn:
  194 +```dart
  195 +int count = Get.find<SharedPreferences>().getInt('counter');
  196 +print(count); // out: 12345
  197 +```
  198 +
  199 +Để xóa một controller đang chạy ngầm của Get:
  200 +
  201 +```dart
  202 +Get.delete<Controller>(); //thường thì Get tự xóa, bạn không cần phải đặt lệnh này.
  203 +```
  204 +
  205 +## Khác nhau giữa phương thức (methods)
  206 +
  207 +Đầu tiên, hãy nói về `fenix` của Get.lazyPut và `permanent`của các phương thức khác.
  208 +
  209 +Sự khác biệt cơ bản giữa `permanent` và `fenix` là cách bạn muốn lưu trữ các cá thể của mình.
  210 +
  211 +Củng cố: theo mặc định, GetX xóa các trường hợp khi chúng không được sử dụng.
  212 +Có nghĩa là: Nếu màn hình 1 có controller 1 và màn hình 2 có controller 2 và bạn xóa route đầu tiên khỏi stack, (chẳng hạn như nếu bạn sử dụng `` Get.off () 'hoặc' `Get.offNamed()``) thì controller 1 bị mất việc sử dụng nó vì vậy nó sẽ bị xóa.
  213 +
  214 +Nhưng nếu bạn muốn chọn sử dụng `permanent: true`, thì controller sẽ không bị mất trong quá trình chuyển đổi này - điều này rất hữu ích cho các dịch vụ mà bạn muốn duy trì hoạt động trong toàn bộ ứng dụng.
  215 +
  216 +Mặt khác, `fenix` dành cho các dịch vụ mà bạn không lo bị mất giữa các lần thay đổi màn hình, nhưng khi bạn cần dịch vụ đó, bạn hy vọng rằng nó vẫn tồn tại. Vì vậy, về cơ bản, nó sẽ loại bỏ controller / service / class không sử dụng, nhưng khi bạn cần, nó sẽ "tạo lại từ đống tro tàn" ở một trường hợp (instance) mới.
  217 +
  218 +Tiếp tục với sự khác biệt giữa các phương pháp:
  219 +
  220 +- Get.put và Get.putAsync tuân theo cùng một thứ tự tạo, với sự khác biệt là một cái sử dụng phương thức không đồng bộ: hai phương thức đó đều tạo và khởi tạo các trường hợp. Cái sử dụng không đồng bộ được chèn trực tiếp vào bộ nhớ, bằng cách sử dụng phương thức nội bộ `insert` với các tham số `permanent: false` và` isSingleton: true` (tham số isSingleton này chỉ nhằm mục đích cho biết liệu nó có sử dụng dependency vào `dependency` hay không hoặc nếu nó được sử dụng dependency vào `FcBuilderFunc`). Sau đó, `Get.find ()` được gọi để khởi tạo ngay lập tức các các trường hợp trên bộ nhớ.
  221 +
  222 +- Get.create: Như tên của nó, nó sẽ "tạo ra" sự dependency cho bạn! Tương tự như `Get.put ()`, nó cũng gọi phương thức nội bộ là `insert` để các trường hợp. Nhưng `permanent` trở thành true và` isSingleton` trở thành false (vì chúng ta đang "tạo" dependency của mình, không có cách nào để nó là một instace singleton, đó là lý do tại sao lại là false). Và bởi vì nó có `permanent: true`, chúng tôi mặc định có lợi ích là không bị mất nó giữa các màn hình! Ngoài ra, `` Get.find () 'không được gọi ngay lập tức, nó phải chờ được sử dụng trong màn hình để được gọi. Nó được tạo ra theo cách này để sử dụng tham số `permanent ', vì vậy, đáng chú ý là` Get.create () `được tạo ra với mục tiêu tạo ra các phiên bản không được chia sẻ, nhưng không bị loại bỏ, như ví dụ: trong listView, mà bạn muốn có một phiên bản duy nhất cho danh sách đó - do đó, Get.create phải được sử dụng cùng với GetWidget.
  223 +
  224 +- Get.lazyPut: Như tên của nó, nó là một quy trình lười biếng. Cá thể được tạo, nhưng nó không được gọi để sử dụng ngay lập tức, nó vẫn đang chờ được gọi. Trái ngược với các phương thức khác, `insert` không được gọi ở đây. Thay vào đó, cá thể được chèn vào một phần khác của bộ nhớ, một phần chịu trách nhiệm cho biết liệu cá thể đó có thể được tạo lại hay không, chúng ta hãy gọi nó là "nhà máy". Nếu chúng ta muốn tạo ra thứ gì đó để sử dụng sau này, nó sẽ không bị trộn lẫn với những thứ đã được sử dụng ngay bây giờ. Và đây là nơi phép thuật của `fenix` đi vào: nếu bạn chọn bỏ` fenix: false`, và `smartManagement` của bạn không phải là` keepFactory`, thì khi sử dụng `Get.find`, instance sẽ thay đổi vị trí trong bộ nhớ từ "nhà máy" đến vùng bộ nhớ cá thể chung. Ngay sau đó, theo mặc định, nó được xóa khỏi "nhà máy". Bây giờ, nếu bạn chọn `fenix: true`, cá thể vẫn tiếp tục tồn tại trong phần dành riêng này, thậm chí sẽ chuyển sang vùng chung, sẽ được gọi lại trong tương lai.
  225 +
  226 +## Bindings
  227 +
  228 +Có lẽ, một trong những điểm khác biệt lớn của gói này là khả năng tích hợp đầy đủ các route, trình quản lý state và trình quản lý dependency.
  229 +Khi một route bị xóa khỏi stack, tất cả các controller, biến và phiên bản của các đối tượng liên quan đến nó sẽ bị xóa khỏi bộ nhớ. Nếu bạn đang sử dụng luồng hoặc bộ hẹn giờ, chúng sẽ tự động bị đóng và bạn không phải lo lắng về bất kỳ điều gì trong số đó.
  230 +Trong phiên bản 2.10 Được triển khai hoàn toàn API bindings.
  231 +Bây giờ bạn không cần sử dụng phương thức init nữa. Bạn thậm chí không cần phải nhập controller của mình nếu bạn không muốn. Bạn có thể khởi động controller và dịch vụ của mình ở nơi thích hợp cho việc đó.
  232 +Lớp Binding là một class sẽ tách riêng việc tiêm dependency, trong khi "bindings" các route đường tới trình quản lý state và trình quản lý dependency.
  233 +Điều này cho phép Nhận biết màn hình nào đang được hiển thị khi một controller cụ thể được sử dụng và biết vị trí và cách vứt bỏ nó.
  234 +Ngoài ra, class Binding sẽ cho phép bạn kiểm soát cấu hình SmartManager. Bạn có thể định cấu hình các phần dependency được sắp xếp khi xóa một route khỏi ngăn xếp hoặc khi widget con đã sử dụng nó được bố trí hoặc không. Bạn sẽ có quản lý dependency thông minh làm việc cho bạn, nhưng ngay cả như vậy, bạn có thể định cấu hình nó theo ý muốn.
  235 +
  236 +### Bindings class
  237 +
  238 +- Tạo một class và implements Binding
  239 +
  240 +```dart
  241 +class HomeBinding implements Bindings {}
  242 +```
  243 +
  244 +IDE của bạn sẽ tự động yêu cầu bạn ghi đè phương thức "dependency" và bạn chỉ cần nhấp vào đèn, ghi đè phương thức và chèn tất cả các class bạn sẽ sử dụng trên route đó:
  245 +
  246 +```dart
  247 +class HomeBinding implements Bindings {
  248 + @override
  249 + void dependencies() {
  250 + Get.lazyPut<HomeController>(() => HomeController());
  251 + Get.put<Service>(()=> Api());
  252 + }
  253 +}
  254 +
  255 +class DetailsBinding implements Bindings {
  256 + @override
  257 + void dependencies() {
  258 + Get.lazyPut<DetailsController>(() => DetailsController());
  259 + }
  260 +}
  261 +```
  262 +
  263 +Bây giờ bạn chỉ cần thông báo route của mình, rằng bạn sẽ sử dụng bindings đó để tạo kết nối giữa trình quản lý route, các dependency và state.
  264 +
  265 +- Sử dụng routes có tên:
  266 +
  267 +```dart
  268 +getPages: [
  269 + GetPage(
  270 + name: '/',
  271 + page: () => HomeView(),
  272 + binding: HomeBinding(),
  273 + ),
  274 + GetPage(
  275 + name: '/details',
  276 + page: () => DetailsView(),
  277 + binding: DetailsBinding(),
  278 + ),
  279 +];
  280 +```
  281 +
  282 +- Sử dụng routes thường:
  283 +
  284 +```dart
  285 +Get.to(Home(), binding: HomeBinding());
  286 +Get.to(DetailsView(), binding: DetailsBinding())
  287 +```
  288 +
  289 +Ở đó, bạn không phải lo lắng về việc quản lý bộ nhớ của ứng dụng của mình nữa, Get sẽ thay bạn làm điều đó.
  290 +
  291 +Lớp Binding được gọi khi một route được gọi, bạn có thể tạo một "InitialBinding trong GetMaterialApp của mình để chèn tất cả các dependency sẽ được tạo.
  292 +
  293 +```dart
  294 +GetMaterialApp(
  295 + initialBinding: SampleBind(),
  296 + home: Home(),
  297 +);
  298 +```
  299 +
  300 +### BindingsBuilder
  301 +
  302 +Cách mặc định để tạo bindings là tạo một class thực hiện các bindings.
  303 +Nhưng cách khác, bạn có thể sử dụng lệnh gọi lại `BindingsBuilder` để bạn có thể chỉ cần sử dụng một hàm để khởi tạo bất cứ thứ gì bạn muốn.
  304 +
  305 +Example:
  306 +
  307 +```dart
  308 +getPages: [
  309 + GetPage(
  310 + name: '/',
  311 + page: () => HomeView(),
  312 + binding: BindingsBuilder(() {
  313 + Get.lazyPut<ControllerX>(() => ControllerX());
  314 + Get.put<Service>(()=> Api());
  315 + }),
  316 + ),
  317 + GetPage(
  318 + name: '/details',
  319 + page: () => DetailsView(),
  320 + binding: BindingsBuilder(() {
  321 + Get.lazyPut<DetailsController>(() => DetailsController());
  322 + }),
  323 + ),
  324 +];
  325 +```
  326 +
  327 +Bằng cách đó, bạn có thể tránh tạo một class Binding cho mỗi routes, làm cho việc này trở nên đơn giản hơn.
  328 +
  329 +Cả hai cách làm việc đều hoàn toàn tốt và chúng tôi muốn bạn sử dụng những gì phù hợp với sở thích của bạn nhất.
  330 +
  331 +### SmartManagement
  332 +
  333 +GetX theo mặc định loại bỏ controller không sử dụng khỏi bộ nhớ, ngay cả khi xảy ra lỗi và widget con sử dụng nó không được xử lý đúng cách.
  334 +Đây được gọi là chế độ quản lý dependency `` đầy đủ`.
  335 +Nhưng nếu bạn muốn thay đổi cách GetX kiểm soát việc xử lý các class, bạn có class `SmartManagement` để bạn có thể thiết lập các hành vi khác nhau.
  336 +
  337 +#### Cách thay đổi
  338 +
  339 +Nếu bạn muốn thay đổi cấu hình này (mà bạn thường không cần) thì đây là cách:
  340 +
  341 +```dart
  342 +void main () {
  343 + runApp(
  344 + GetMaterialApp(
  345 + smartManagement: SmartManagement.onlyBuilders //here
  346 + home: Home(),
  347 + )
  348 + )
  349 +}
  350 +```
  351 +
  352 +#### SmartManagement.full
  353 +
  354 +Nó là một trong những mặc định. Loại bỏ các class không được sử dụng và không được đặt thành vĩnh viễn. Trong phần lớn các trường hợp, bạn sẽ muốn giữ nguyên cấu hình này. Nếu bạn mới sử dụng GetX thì đừng thay đổi điều này.
  355 +
  356 +#### SmartManagement.onlyBuilders
  357 +Với tùy chọn này, chỉ những controller bắt đầu trong `init: 'hoặc được tải vào Binding với` `Get.lazyPut ()` mới được xử lý.
  358 +
  359 +Nếu bạn sử dụng `Get.put () 'hoặc' Get.putAsync ()` hoặc bất kỳ cách tiếp cận nào khác, SmartManagement sẽ không có quyền loại trừ sự dependency này.
  360 +
  361 +Với hành vi mặc định, ngay cả các widget con được khởi tạo bằng "Get.put" sẽ bị xóa, không giống như SmartManagement.onlyBuilders.
  362 +
  363 +#### SmartManagement.keepFactory
  364 +
  365 +Cũng giống như SmartManagement.full, nó sẽ loại bỏ các phần dependency của nó khi nó không được sử dụng nữa. Tuy nhiên, nó sẽ giữ nguyên chế độ factory của họ, có nghĩa là nó sẽ tạo lại phần dependency nếu bạn cần lại phiên bản đó.
  366 +
  367 +### Cách bindings làm việc ngầm
  368 +Các liên kết tạo ra các factory tạm thời, được tạo ra ngay khi bạn nhấp để chuyển sang màn hình khác và sẽ bị phá hủy ngay sau khi hoạt ảnh thay đổi màn hình xảy ra.
  369 +Điều này xảy ra quá nhanh đến nỗi máy phân tích thậm chí sẽ không thể đăng ký nó.
  370 +Khi bạn điều hướng đến màn hình này một lần nữa, một factory tạm thời mới sẽ được gọi, vì vậy điều này thích hợp hơn khi sử dụng SmartManagement.keepFactory, nhưng nếu bạn không muốn tạo Bindings hoặc muốn giữ tất cả các dependency của mình trên cùng một Binding, thì chắc chắn sẽ giúp ích cho bạn.
  371 +Các factory chiếm ít bộ nhớ, chúng không chứa các cá thể mà là một chức năng có "hình dạng" của class đó mà bạn muốn.
  372 +Điều này có chi phí bộ nhớ rất thấp, nhưng vì mục đích của lib này là để đạt được hiệu suất tối đa có thể bằng cách sử dụng tài nguyên tối thiểu, Get xóa ngay cả các factory theo mặc định.
  373 +Sử dụng cái nào thuận tiện nhất cho bạn.
  374 +
  375 +## Chí ú
  376 +
  377 +- KHÔNG SỬ DỤNG SmartManagement.keepFactory nếu bạn đang sử dụng nhiều Binding. Nó được thiết kế để sử dụng mà không có Bindings, hoặc với một Bindings duy nhất được liên kết trong `initialBinding` của GetMaterialApp.
  378 +
  379 +- Việc sử dụng Bindings là hoàn toàn tùy chọn, nếu muốn, bạn có thể sử dụng `Get.put () 'và' Get.find()` trên các class sử dụng controller nhất định mà không gặp bất kỳ vấn đề gì.
  380 +Tuy nhiên, nếu bạn làm việc với Service hoặc bất kỳ abstract nào khác, tôi khuyên bạn nên sử dụng Bindings để tổ chức tốt hơn.
  1 +- [Quản lý route](#route-management)
  2 + - [Hướng dẫn sử dụng trước khi dùng](#how-to-use)
  3 + - [Điều hướng không cần tên](#navigation-without-named-routes)
  4 + - [Điều hướng cần tên](#navigation-with-named-routes)
  5 + - [Gửi data cho route có tên](#send-data-to-named-routes)
  6 + - [Dynamic urls links](#dynamic-urls-links)
  7 + - [Middleware](#middleware)
  8 + - [Điều hướng không cần context](#navigation-without-context)
  9 + - [SnackBars](#snackbars)
  10 + - [Dialogs](#dialogs)
  11 + - [BottomSheets](#bottomsheets)
  12 + - [Điều hướng lồng (Nested Navigation)](#nested-navigation)
  13 +
  14 +# Quản lý route
  15 +
  16 +Đây là lời giải thích đầy đủ về tất cả những gì có cho Getx khi vấn đề là quản lý routes.
  17 +
  18 +## Hướng dẫn sử dụng trước khi dùng
  19 +
  20 +Thêm cái này vào file pubspec.yaml của bạn:
  21 +
  22 +```yaml
  23 +dependencies:
  24 + get:
  25 +```
  26 +
  27 +Nếu bạn định sử dụng các routes / snackbars / dialogs / bottomsheets mà không có "context" hoặc sử dụng các API cấp cao, bạn chỉ cần thêm Get trước MaterialApp của mình, biến nó thành GetMaterialApp và tung hành!
  28 +
  29 +```dart
  30 +GetMaterialApp( // Before: MaterialApp(
  31 + home: MyHome(),
  32 +)
  33 +```
  34 +
  35 +## Điều hướng không cần tên
  36 +
  37 +Để điều hướng đến một màn hình mới:
  38 +
  39 +```dart
  40 +Get.to(NextScreen());
  41 +```
  42 +
  43 +Để đóng snackbars, dialog, bottomsheets hoặc bất cứ thứ gì bạn thường đóng bằng Navigator.pop (context);
  44 +
  45 +```dart
  46 +Get.back();
  47 +```
  48 +
  49 +Để chuyển đến màn hình tiếp theo và không có tùy chọn nào để quay lại màn hình trước đó (để sử dụng trong SplashScreens, màn hình đăng nhập, v.v.)
  50 +
  51 +```dart
  52 +Get.off(NextScreen());
  53 +```
  54 +
  55 +Để chuyển đến màn hình tiếp theo và hủy tất cả các lộ trình trước đó (hữu ích trong giỏ hàng, polls và test)
  56 +
  57 +```dart
  58 +Get.offAll(NextScreen());
  59 +```
  60 +
  61 +Để điều hướng đến routes tiếp theo và nhận hoặc cập nhật dữ liệu ngay sau khi bạn trở về từ routes đó:
  62 +
  63 +```dart
  64 +var data = await Get.to(Payment());
  65 +```
  66 +
  67 +trên màn hình khác, gửi dữ liệu cho routes trước đó:
  68 +
  69 +```dart
  70 +Get.back(result: 'success');
  71 +```
  72 +
  73 +And use it:
  74 +
  75 +ex:
  76 +
  77 +```dart
  78 +if(data == 'success') madeAnything();
  79 +```
  80 +
  81 +Bạn không muốn học cú pháp của chúng tôi?
  82 +Chỉ cần thay đổi Navigator (chữ in hoa) thành navigator (chữ thường) và bạn sẽ có tất cả các chức năng của điều hướng tiêu chuẩn mà không cần phải sử dụng "context"
  83 +Thí dụ:
  84 +
  85 +```dart
  86 +
  87 +// Default Flutter navigator
  88 +Navigator.of(context).push(
  89 + context,
  90 + MaterialPageRoute(
  91 + builder: (BuildContext context) {
  92 + return HomePage();
  93 + },
  94 + ),
  95 +);
  96 +
  97 +// Get using Flutter syntax without needing context
  98 +navigator.push(
  99 + MaterialPageRoute(
  100 + builder: (_) {
  101 + return HomePage();
  102 + },
  103 + ),
  104 +);
  105 +
  106 +// Get syntax (It is much better, but you have the right to disagree)
  107 +Get.to(HomePage());
  108 +
  109 +
  110 +```
  111 +
  112 +## Điều hướng cần tên
  113 +
  114 +- Nếu bạn thích điều hướng bằng tên, Get cũng hỗ trợ điều này.
  115 +
  116 +To navigate to nextScreen
  117 +
  118 +```dart
  119 +Get.toNamed("/NextScreen");
  120 +```
  121 +
  122 +Để điều hướng và xóa màn hình trước đó khỏi cây widget.
  123 +
  124 +```dart
  125 +Get.offNamed("/NextScreen");
  126 +```
  127 +
  128 +Để điều hướng và xóa tất cả các màn hình trước đó khỏi cây widget.
  129 +
  130 +```dart
  131 +Get.offAllNamed("/NextScreen");
  132 +```
  133 +
  134 +Để định dạng routes, sử dụng GetMaterialApp:
  135 +
  136 +```dart
  137 +void main() {
  138 + runApp(
  139 + GetMaterialApp(
  140 + initialRoute: '/',
  141 + getPages: [
  142 + GetPage(name: '/', page: () => MyHomePage()),
  143 + GetPage(name: '/second', page: () => Second()),
  144 + GetPage(
  145 + name: '/third',
  146 + page: () => Third(),
  147 + transition: Transition.zoom
  148 + ),
  149 + ],
  150 + )
  151 + );
  152 +}
  153 +```
  154 +
  155 +Để xử lý điều hướng đến các routes không được xác định (lỗi 404), bạn có thể xác định trang 'không xác định' trong GetMaterialApp.
  156 +
  157 +```dart
  158 +void main() {
  159 + runApp(
  160 + GetMaterialApp(
  161 + unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
  162 + initialRoute: '/',
  163 + getPages: [
  164 + GetPage(name: '/', page: () => MyHomePage()),
  165 + GetPage(name: '/second', page: () => Second()),
  166 + ],
  167 + )
  168 + );
  169 +}
  170 +```
  171 +
  172 +### Gửi data cho route có tên
  173 +
  174 +Chỉ cần gửi những gì bạn muốn cho các đối số (arguments). Get chấp nhận bất kỳ thứ gì ở đây, cho dù đó là String, Map, List hay thậm chí là một class trường hợp.
  175 +
  176 +```dart
  177 +Get.toNamed("/NextScreen", arguments: 'Get is the best');
  178 +```
  179 +
  180 +Trong class controller của bạn:
  181 +
  182 +```dart
  183 +print(Get.arguments);
  184 +//print out: Get is the best
  185 +```
  186 +
  187 +### Dynamic urls links
  188 +
  189 +Get hỗ trợ các url động nâng cao giống như trên Web. Các nhà phát triển web có lẽ đã muốn tính năng này trên Flutter và rất có thể đã thấy một gói hứa hẹn tính năng này và cung cấp một cú pháp hoàn toàn khác so với một URL sẽ có trên web, và Get cũng giải quyết được điều này.
  190 +
  191 +```dart
  192 +Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo");
  193 +```
  194 +
  195 +trong controller/bloc/stateful/stateless của class:
  196 +
  197 +```dart
  198 +print(Get.parameters['id']);
  199 +// out: 354
  200 +print(Get.parameters['name']);
  201 +// out: Enzo
  202 +```
  203 +
  204 +Bạn có thể đặt NamedParameters với Get dễ dàng:
  205 +
  206 +```dart
  207 +void main() {
  208 + runApp(
  209 + GetMaterialApp(
  210 + initialRoute: '/',
  211 + getPages: [
  212 + GetPage(
  213 + name: '/',
  214 + page: () => MyHomePage(),
  215 + ),
  216 + GetPage(
  217 + name: '/profile/',
  218 + page: () => MyProfile(),
  219 + ),
  220 + //You can define a different page for routes with arguments, and another without arguments, but for that you must use the slash '/' on the route that will not receive arguments as above.
  221 + GetPage(
  222 + name: '/profile/:user',
  223 + page: () => UserProfile(),
  224 + ),
  225 + GetPage(
  226 + name: '/third',
  227 + page: () => Third(),
  228 + transition: Transition.cupertino
  229 + ),
  230 + ],
  231 + )
  232 + );
  233 +}
  234 +```
  235 +
  236 +Gửi data bằng tên
  237 +
  238 +```dart
  239 +Get.toNamed("/profile/34954");
  240 +```
  241 +
  242 +Trên màn hình thứ hai, lấy dữ liệu theo tham số (parameters)
  243 +
  244 +```dart
  245 +print(Get.parameters['user']);
  246 +// out: 34954
  247 +```
  248 +
  249 +hoặc gửi nhiều tham số như thế này
  250 +
  251 +```dart
  252 +Get.toNamed("/profile/34954?flag=true&country=italy");
  253 +```
  254 +or
  255 +```dart
  256 +var parameters = <String, String>{"flag": "true","country": "italy",};
  257 +Get.toNamed("/profile/34954", parameters: parameters);
  258 +```
  259 +
  260 +Trên màn hình thứ hai, lấy dữ liệu theo các tham số như thường lệ
  261 +
  262 +```dart
  263 +print(Get.parameters['user']);
  264 +print(Get.parameters['flag']);
  265 +print(Get.parameters['country']);
  266 +// out: 34954 true italy
  267 +```
  268 +
  269 +
  270 +
  271 +Và bây giờ, tất cả những gì bạn cần làm là sử dụng Get.toNamed () để điều hướng các routes đã đặt tên của bạn mà không cần bất kỳ "context" nào (bạn có thể gọi các routes của mình trực tiếp từ BLoC hoặc lớp Bộ điều khiển) và khi ứng dụng của bạn được biên dịch lên web, các routes sẽ xuất hiện trong url <3
  272 +
  273 +### Middleware
  274 +
  275 +Nếu bạn muốn nghe Get events để kích hoạt các hành động, bạn có thể sử dụng routingCallback cho nó
  276 +
  277 +```dart
  278 +GetMaterialApp(
  279 + routingCallback: (routing) {
  280 + if(routing.current == '/second'){
  281 + openAds();
  282 + }
  283 + }
  284 +)
  285 +```
  286 +
  287 +Nếu bạn không sử dụng GetMaterialApp, bạn có thể sử dụng API thủ công để đính kèm trình quan sát Middleware.
  288 +
  289 +```dart
  290 +void main() {
  291 + runApp(
  292 + MaterialApp(
  293 + onGenerateRoute: Router.generateRoute,
  294 + initialRoute: "/",
  295 + navigatorKey: Get.key,
  296 + navigatorObservers: [
  297 + GetObserver(MiddleWare.observer), // HERE !!!
  298 + ],
  299 + ),
  300 + );
  301 +}
  302 +```
  303 +
  304 +Tạo một MiddleWare class
  305 +
  306 +```dart
  307 +class MiddleWare {
  308 + static observer(Routing routing) {
  309 + /// You can listen in addition to the routes, the snackbars, dialogs and bottomsheets on each screen.
  310 + ///If you need to enter any of these 3 events directly here,
  311 + ///you must specify that the event is != Than you are trying to do.
  312 + if (routing.current == '/second' && !routing.isSnackbar) {
  313 + Get.snackbar("Hi", "You are on second route");
  314 + } else if (routing.current =='/third'){
  315 + print('last route called');
  316 + }
  317 + }
  318 +}
  319 +```
  320 +
  321 +Bây giờ, hãy sử dụng Get trên code của bạn:
  322 +
  323 +```dart
  324 +class First extends StatelessWidget {
  325 + @override
  326 + Widget build(BuildContext context) {
  327 + return Scaffold(
  328 + appBar: AppBar(
  329 + leading: IconButton(
  330 + icon: Icon(Icons.add),
  331 + onPressed: () {
  332 + Get.snackbar("hi", "i am a modern snackbar");
  333 + },
  334 + ),
  335 + title: Text('First Route'),
  336 + ),
  337 + body: Center(
  338 + child: ElevatedButton(
  339 + child: Text('Open route'),
  340 + onPressed: () {
  341 + Get.toNamed("/second");
  342 + },
  343 + ),
  344 + ),
  345 + );
  346 + }
  347 +}
  348 +
  349 +class Second extends StatelessWidget {
  350 + @override
  351 + Widget build(BuildContext context) {
  352 + return Scaffold(
  353 + appBar: AppBar(
  354 + leading: IconButton(
  355 + icon: Icon(Icons.add),
  356 + onPressed: () {
  357 + Get.snackbar("hi", "i am a modern snackbar");
  358 + },
  359 + ),
  360 + title: Text('second Route'),
  361 + ),
  362 + body: Center(
  363 + child: ElevatedButton(
  364 + child: Text('Open route'),
  365 + onPressed: () {
  366 + Get.toNamed("/third");
  367 + },
  368 + ),
  369 + ),
  370 + );
  371 + }
  372 +}
  373 +
  374 +class Third extends StatelessWidget {
  375 + @override
  376 + Widget build(BuildContext context) {
  377 + return Scaffold(
  378 + appBar: AppBar(
  379 + title: Text("Third Route"),
  380 + ),
  381 + body: Center(
  382 + child: ElevatedButton(
  383 + onPressed: () {
  384 + Get.back();
  385 + },
  386 + child: Text('Go back!'),
  387 + ),
  388 + ),
  389 + );
  390 + }
  391 +}
  392 +```
  393 +
  394 +## Điều hướng không cần context
  395 +
  396 +### SnackBars
  397 +
  398 +Để có một SnackBar đơn giản với Flutter, bạn phải lấy context của Scaffold, hoặc bạn phải sử dụng GlobalKey được gắn vào Scaffold của bạn
  399 +
  400 +```dart
  401 +final snackBar = SnackBar(
  402 + content: Text('Hi!'),
  403 + action: SnackBarAction(
  404 + label: 'I am a old and ugly snackbar :(',
  405 + onPressed: (){}
  406 + ),
  407 +);
  408 +// Find the Scaffold in the widget tree and use
  409 +// it to show a SnackBar.
  410 +Scaffold.of(context).showSnackBar(snackBar);
  411 +```
  412 +
  413 +With Get:
  414 +
  415 +```dart
  416 +Get.snackbar('Hi', 'i am a modern snackbar');
  417 +```
  418 +
  419 +Với Get, tất cả những gì bạn phải làm là gọi thanh Get.snackbar từ bất kỳ đâu trong code của bạn hoặc tùy chỉnh nó theo cách bạn muốn!
  420 +
  421 +```dart
  422 +Get.snackbar(
  423 + "Hey i'm a Get SnackBar!", // title
  424 + "It's unbelievable! I'm using SnackBar without context, without boilerplate, without Scaffold, it is something truly amazing!", // message
  425 + icon: Icon(Icons.alarm),
  426 + shouldIconPulse: true,
  427 + onTap:(){},
  428 + barBlur: 20,
  429 + isDismissible: true,
  430 + duration: Duration(seconds: 3),
  431 +);
  432 +
  433 +
  434 + ////////// ALL FEATURES //////////
  435 + // Color colorText,
  436 + // Duration duration,
  437 + // SnackPosition snackPosition,
  438 + // Widget titleText,
  439 + // Widget messageText,
  440 + // bool instantInit,
  441 + // Widget icon,
  442 + // bool shouldIconPulse,
  443 + // double maxWidth,
  444 + // EdgeInsets margin,
  445 + // EdgeInsets padding,
  446 + // double borderRadius,
  447 + // Color borderColor,
  448 + // double borderWidth,
  449 + // Color backgroundColor,
  450 + // Color leftBarIndicatorColor,
  451 + // List<BoxShadow> boxShadows,
  452 + // Gradient backgroundGradient,
  453 + // TextButton mainButton,
  454 + // OnTap onTap,
  455 + // bool isDismissible,
  456 + // bool showProgressIndicator,
  457 + // AnimationController progressIndicatorController,
  458 + // Color progressIndicatorBackgroundColor,
  459 + // Animation<Color> progressIndicatorValueColor,
  460 + // SnackStyle snackStyle,
  461 + // Curve forwardAnimationCurve,
  462 + // Curve reverseAnimationCurve,
  463 + // Duration animationDuration,
  464 + // double barBlur,
  465 + // double overlayBlur,
  466 + // Color overlayColor,
  467 + // Form userInputForm
  468 + ///////////////////////////////////
  469 +```
  470 +
  471 +Nếu bạn thích snackbar truyền thống hoặc muốn tùy chỉnh nó từ đầu, bao gồm chỉ thêm một dòng (Get.snackbar sử dụng tiêu đề và thông báo bắt buộc), bạn có thể sử dụng
  472 +`Get.rawSnackbar ()`; 'cung cấp API RAW trên đó Get.
  473 +
  474 +### Dialogs
  475 +
  476 +To open dialog:
  477 +
  478 +```dart
  479 +Get.dialog(YourDialogWidget());
  480 +```
  481 +
  482 +To open default dialog:
  483 +
  484 +```dart
  485 +Get.defaultDialog(
  486 + onConfirm: () => print("Ok"),
  487 + middleText: "Dialog made in 3 lines of code"
  488 +);
  489 +```
  490 +
  491 +Bạn cũng có thể sử dụng Get.generalDialog thay vì showGeneralDialog.
  492 +
  493 +Đối với tất cả các tiện ích hộp thoại Flutter khác, bao gồm cả cupertinos, bạn có thể sử dụng Get.overlayContext thay vì context và mở nó ở bất kỳ đâu trong mã của bạn.
  494 +Đối với các widget không sử dụng Overlay, bạn có thể sử dụng Get.context.
  495 +Hai context này sẽ hoạt động trong 99% trường hợp để thay thế context của UI của bạn, ngoại trừ các trường hợp trong đó inheritWidget được sử dụng mà không có context điều hướng.
  496 +
  497 +### BottomSheets
  498 +
  499 +Get.bottomSheet giống như showModalBottomSheet, nhưng không cần context.
  500 +
  501 +```dart
  502 +Get.bottomSheet(
  503 + Container(
  504 + child: Wrap(
  505 + children: <Widget>[
  506 + ListTile(
  507 + leading: Icon(Icons.music_note),
  508 + title: Text('Music'),
  509 + onTap: () {}
  510 + ),
  511 + ListTile(
  512 + leading: Icon(Icons.videocam),
  513 + title: Text('Video'),
  514 + onTap: () {},
  515 + ),
  516 + ],
  517 + ),
  518 + )
  519 +);
  520 +```
  521 +
  522 +## Điều hướng lồng (Nested Navigation)
  523 +
  524 +Làm cho điều hướng lồng (nested navigation) của Flutter thậm chí còn dễ dàng hơn.
  525 +Bạn không cần context và bạn sẽ tìm thấy stack điều hướng của mình theo Id.
  526 +
  527 +- CHÍ Ú: Việc tạo các stack điều hướng song song có thể gây nguy hiểm. Lý tưởng nhất là không sử dụng NestedNavigators, hoặc sử dụng một cách tối thiểu. Nếu dự án của bạn yêu cầu, hãy tiếp tục, nhưng hãy nhớ rằng việc giữ nhiều stack điều hướng trong bộ nhớ có thể không phải là một ý tưởng hay cho việc tiêu thụ RAM.
  528 +
  529 +Xem nó code đơn giản nè:
  530 +
  531 +```dart
  532 +Navigator(
  533 + key: Get.nestedKey(1), // create a key by index
  534 + initialRoute: '/',
  535 + onGenerateRoute: (settings) {
  536 + if (settings.name == '/') {
  537 + return GetPageRoute(
  538 + page: () => Scaffold(
  539 + appBar: AppBar(
  540 + title: Text("Main"),
  541 + ),
  542 + body: Center(
  543 + child: TextButton(
  544 + color: Colors.blue,
  545 + onPressed: () {
  546 + Get.toNamed('/second', id:1); // navigate by your nested route by index
  547 + },
  548 + child: Text("Go to second"),
  549 + ),
  550 + ),
  551 + ),
  552 + );
  553 + } else if (settings.name == '/second') {
  554 + return GetPageRoute(
  555 + page: () => Center(
  556 + child: Scaffold(
  557 + appBar: AppBar(
  558 + title: Text("Main"),
  559 + ),
  560 + body: Center(
  561 + child: Text("second")
  562 + ),
  563 + ),
  564 + ),
  565 + );
  566 + }
  567 + }
  568 +),
  569 +```
  1 +* [Quản lý State](#state-management)
  2 + + [Quản lý Reactive State](#reactive-state-manager)
  3 + - [Lợi thế](#advantages)
  4 + - [Hiệu suất tối đa:](#maximum-performance)
  5 + - [Khai báo một biến phản ứng (reactive variable)](#declaring-a-reactive-variable)
  6 + - [Thât dễ khi có reactive state.](#having-a-reactive-state-is-easy)
  7 + - [Sử dụng values trong View](#using-the-values-in-the-view)
  8 + - [Điều kiện để tái tạo lại](#conditions-to-rebuild)
  9 + - [Nơi .obs có thể dùng](#where-obs-can-be-used)
  10 + - [Chí ú về Lists](#note-about-lists)
  11 + - [Tại sao tôi phải dùng .value](#why-i-have-to-use-value)
  12 + - [Obx()](#obx)
  13 + - [Workers](#workers)
  14 + + [Quản lý State đơn giản](#simple-state-manager)
  15 + - [Lợi thế](#advantages-1)
  16 + - [Sử dụng](#usage)
  17 + - [Cách GetX sử dụng controllers](#how-it-handles-controllers)
  18 + - [Không cần StatefulWidget nữa!](#you-wont-need-statefulwidgets-anymore)
  19 + - [Tại sao GetX tồn tại?](#why-it-exists)
  20 + - [Cách sử dụng khác](#other-ways-of-using-it)
  21 + - [IDs độc nhất](#unique-ids)
  22 + + [Trộn hai trình quản lý state](#mixing-the-two-state-managers)
  23 + + [GetBuilder vs GetX vs Obx vs MixinBuilder](#getbuilder-vs-getx-vs-obx-vs-mixinbuilder)
  24 +
  25 +# Quản lý State
  26 +
  27 +GetX không sử dụng Streams hoặc ChangeNotifier như các quản lý state khác. Tại sao? Ngoài việc xây dựng các ứng dụng cho android, iOS, web, linux, macos và linux, với GetX bạn có thể xây dựng các ứng dụng máy chủ với cú pháp tương tự như Flutter / GetX. Để cải thiện thời gian phản hồi và giảm mức tiêu thụ RAM, chúng tôi đã tạo GetValue và GetStream, là các giải pháp có độ trễ thấp mang lại nhiều hiệu suất với chi phí vận hành thấp. Chúng tôi sử dụng cơ sở này để xây dựng tất cả các nguồn lực của mình, bao gồm cả quản lý state.
  28 +
  29 +* _Phức hợp_: Một số quản lý state rất phức tạp và có rất nhiều cơ sở hạ tầng. Với GetX, bạn không phải xác định một class cho mỗi event, code rất rõ ràng và rõ ràng, và bạn làm được nhiều việc hơn bằng cách viết ít hơn. Nhiều người đã từ bỏ Flutter vì chủ đề này, và cuối cùng họ đã có một giải pháp đơn giản đến mức đần độn để quản lý các state.
  30 +* _Không trình tạo mã_: Bạn dành một nửa thời gian phát triển để viết logic ứng dụng của mình. Một số quản lý state dựa vào trình tạo mã để có mã có thể đọc được ở mức tối thiểu. Việc thay đổi một biến và phải chạy build_runner có thể gây mất hiệu quả, chuyện này rất ngốn thời gian chờ đợi sau khi quét sạch sẽ rất lâu và bạn phải uống rất nhiều cà phê.
  31 +
  32 +Với GetX, mọi thứ đều hoạt động và độc lập với trình tạo mã, giúp tăng năng suất của bạn trong mọi khía cạnh phát triển của bạn.
  33 +
  34 +* _Không phụ thuộc vào context_: Có thể bạn đã cần gửi context của chế độ xem của mình tới controller, làm cho khả năng kết hợp của View với business logic của bạn cao hơn. Bạn có thể phải sử dụng một dependency cho một nơi không có context và phải chuyển context qua các class và hàm khác nhau. Điều này không tồn tại với GetX. Bạn có quyền truy cập vào controller của mình từ bên trong controller mà không cần bất kỳ context nào. Bạn không cần phải gửi context theo tham số vì không có gì theo nghĩa đen.
  35 +* _Kiểm soát hạt_: Hầu hết các quản lý state đều dựa trên ChangeNotifier. ChangeNotifier sẽ thông báo cho tất cả các widget phụ thuộc vào nó khi thông báo cho các widget được gọi. Nếu bạn có 40 widget con trên một màn hình, trong đó có một biến thuộc class ChangeNotifier của bạn, khi bạn cập nhật một widget con, tất cả chúng sẽ được xây dựng lại.
  36 +
  37 +Với GetX, ngay cả các widget lồng nhau cũng được tôn trọng. Nếu bạn có Obx đang xem ListView của bạn và người khác đang xem hộp kiểm bên trong ListView, thì khi thay đổi giá trị CheckBox, chỉ nó mới được cập nhật, khi thay đổi giá trị List, chỉ ListView sẽ được cập nhật.
  38 +
  39 +* _Chỉ tái tạo lại nếu biến CẦN thay đổi_: GetX có tính năng kiểm soát streams, điều đó có nghĩa là nếu bạn hiển thị Text là 'Kaiser', nếu bạn thay đổi lại biến có thể quan sát thành 'Kaiser', widget sẽ không được tạo lại. Đó là bởi vì GetX biết rằng 'Kaiser' đã được hiển thị trong Văn bản và sẽ không thực hiện các thao tác tái tạo không cần thiết.
  40 +
  41 +Hầu hết (nếu không phải tất cả) các trình quản lý state hiện tại sẽ xây dựng lại trên màn hình.
  42 +
  43 +## Quản lý Reactive State
  44 +
  45 +Lập trình phản ứng (Reactive programming) có thể khiến nhiều người xa lánh vì nó được cho là phức tạp. GetX biến lập trình phản ứng thành một thứ khá đơn giản:
  46 +
  47 +* Bạn sẽ không cần tạo StreamControllers.
  48 +* Bạn sẽ không cần tạo StreamBuilder cho mỗi biến
  49 +* Bạn sẽ không cần phải tạo một class cho mỗi state.
  50 +* Bạn sẽ không cần tạo get cho một giá trị ban đầu.
  51 +
  52 +Lập trình phản ứng với Get dễ dàng như sử dụng setState.
  53 +
  54 +Hãy tưởng tượng rằng bạn có một biến tên và muốn rằng mỗi khi bạn thay đổi nó, tất cả các widget sử dụng nó sẽ được tự động thay đổi.
  55 +
  56 +Đây là count variable của bạn:
  57 +
  58 +``` dart
  59 +var name = 'Khang Huỳnh';
  60 +```
  61 +
  62 +Để làm cho nó có thể quan sát được, bạn chỉ cần thêm ".obs" vào cuối nó:
  63 +
  64 +``` dart
  65 +var name = 'Khang Huỳnh'.obs;
  66 +```
  67 +
  68 +Chỉ vậy thôi, chỉ *vậy thôi* người ơi~
  69 +
  70 +Từ bây giờ, chúng ta có thể tham chiếu đến các biến reactive - ". Obs" (có thể thay thế) này là _Rx_.
  71 +
  72 +Chúng tôi đã làm gì phía dưới class code? Chúng tôi đã tạo một `Stream` của `String`, được gán giá trị ban đầu `"Khang Huỳnh"`, chúng tôi đã thông báo cho tất cả các widget con sử dụng `"Khang Huỳnh"` rằng chúng hiện "thuộc về" biến này và khi giá trị _Rx_ thay đổi, chúng phải thay đổi theo.
  73 +Đây là **phép màu của GetX**, nhờ vào khả năng của Dart.
  74 +
  75 +Tuy nhiên, như chúng ta đã biết, một `Widget` chỉ có thể được thay đổi nếu nó nằm bên trong một hàm, bởi vì các class tĩnh không có quyền" tự động thay đổi ".
  76 +
  77 +Bạn sẽ cần tạo một `StreamBuilder`, đăng ký biến này để lắng nghe các thay đổi và tạo một "stream" các` StreamBuilder` lồng nhau nếu bạn muốn thay đổi một số biến trong cùng một phạm vi, phải không?
  78 +
  79 +Không, bạn không cần `StreamBuilder`, nhưng bạn đã đúng về các class tĩnh.
  80 +
  81 +Theo quan điểm, chúng ta thường có rất nhiều bảng soạn sẵn khi chúng ta muốn thay đổi một Widget cụ thể, đó là cách Flutter.
  82 +Với ** GetX **, bạn cũng có thể quên mã soạn sẵn này.
  83 +
  84 +`StreamBuilder (…)`? `initialValue:…`? `builder:…`? Không, bạn chỉ cần đặt biến này bên trong Widget `Obx ()`.
  85 +
  86 +``` dart
  87 +Obx (() => Text (controller.name));
  88 +```
  89 +
  90 +_Bạn cần nhớ gì?_ Chỉ `Obx(() =>` .
  91 +
  92 +Bạn chỉ đang chuyển Widget đó thông qua một hàm mũi tên vào một `Obx ()` ("Observer" của _Rx_).
  93 +
  94 +`Obx` khá thông minh và sẽ chỉ thay đổi nếu giá trị của `controller.name` thay đổi.
  95 +
  96 +Nếu `name` là` "Kaiser" `và bạn thay đổi nó thành` "Kaiser" `(` name.value = "Kaiser" `), vì nó giống như` giá trị` như trước, sẽ không có gì thay đổi trên màn hình, và `Obx`, để tiết kiệm tài nguyên, sẽ đơn giản bỏ qua giá trị mới và không xây dựng lại Widget. **Tuyệt vời ông mặt trời chứ?**
  97 +
  98 +> So, what if I have 5 _Rx_ (observable) variables within an `Obx` ?
  99 +
  100 +Nó sẽ chỉ cập nhật khi ** bất kỳ ** nào trong số chúng thay đổi.
  101 +
  102 +> And if I have 30 variables in a class, when I update one, will it update **all** the variables that are in that class?
  103 +
  104 +Không, chỉ **Widget cụ thể** sử dụng biến _Rx_ đó.
  105 +
  106 +Vì vậy, **GetX** chỉ cập nhật màn hình, khi biến _Rx_ thay đổi giá trị của nó.
  107 +
  108 +```
  109 +
  110 +final isOpen = false.obs;
  111 +
  112 +// NOTHING will happen... same value.
  113 +void onButtonTap() => isOpen.value=false;
  114 +```
  115 +
  116 +### Lợi thế
  117 +
  118 +**GetX()** giúp bạn khi bạn cần kiểm soát **chi tiết** đối với những gì đang được cập nhật.
  119 +
  120 +Nếu bạn không cần `ID duy nhất`, vì tất cả các biến của bạn sẽ được sửa đổi khi bạn thực hiện một hành động, thì hãy sử dụng` GetBuilder`,
  121 +bởi vì nó là một Trình cập nhật state đơn giản (trong các khối, như `setState ()` '), được tạo chỉ trong một vài dòng mã.
  122 +Nó được làm đơn giản, ít ảnh hưởng đến CPU nhất và chỉ để thực hiện một mục đích duy nhất (xây dựng lại _State_) và sử dụng tài nguyên tối thiểu có thể.
  123 +
  124 +Nếu bạn cần một Trình quản lý state **mạnh mẽ**, bạn không thể làm sai với **GetX**.
  125 +
  126 +Nó không hoạt động với các biến, nhưng __flows__, mọi thứ trong đó đều là `Streams`.
  127 +
  128 +Bạn có thể sử dụng _rxDart_ kết hợp với nó, vì mọi thứ đều là `Luồng`,
  129 +bạn có thể nghe `event` của từng" biến _Rx_ ",
  130 +bởi vì mọi thứ trong đó đều là `Streams`.
  131 +
  132 +Nó thực sự là một cách tiếp cận _BLoC_, dễ dàng hơn _MobX_ và không có trình tạo code hoặc decorations.
  133 +Bạn có thể biến **mọi thứ** thành một _"Observable" _ chỉ với một `.obs`.
  134 +
  135 +### Hiệu suất tối đa:
  136 +
  137 +Ngoài việc có một thuật toán thông minh để xây dựng lại tối thiểu, **GetX** sử dụng trình so sánh để đảm bảo rằng Bang đã thay đổi.
  138 +
  139 +Nếu bạn gặp bất kỳ lỗi nào trong ứng dụng của mình và gửi một bản thay đổi state, **GetX** sẽ đảm bảo rằng nó sẽ không gặp sự cố.
  140 +
  141 +Với **GetX** State chỉ thay đổi nếu `giá trị` thay đổi.
  142 +Đó là sự khác biệt chính giữa **GetX** và việc sử dụng _ `computed` từ MobX_.
  143 +Khi kết hợp hai __observables__, và một thay đổi; trình nghe của _observable_ đó cũng sẽ thay đổi.
  144 +
  145 +Với **GetX**, nếu bạn nối hai biến, `GetX ()` (tương tự như `Observer ()`) sẽ chỉ xây dựng lại nếu nó ngụ ý thay đổi state thực sự.
  146 +
  147 +### Khai báo một biến phản ứng (reactive variable)
  148 +
  149 +Bạn có 3 cách để thay đổi variable thành "observable".
  150 +
  151 +1 - Sử dụng **`Rx{Type}`**.
  152 +
  153 +``` dart
  154 +// initial value is recommended, but not mandatory
  155 +final name = RxString('');
  156 +final isLogged = RxBool(false);
  157 +final count = RxInt(0);
  158 +final balance = RxDouble(0.0);
  159 +final items = RxList<String>([]);
  160 +final myMap = RxMap<String, int>({});
  161 +```
  162 +
  163 +2 - Sử dụng **`Rx`** và dùng Darts Generics, `Rx<Type>`
  164 +
  165 +``` dart
  166 +final name = Rx<String>('');
  167 +final isLogged = Rx<Bool>(false);
  168 +final count = Rx<Int>(0);
  169 +final balance = Rx<Double>(0.0);
  170 +final number = Rx<Num>(0);
  171 +final items = Rx<List<String>>([]);
  172 +final myMap = Rx<Map<String, int>>({});
  173 +
  174 +// Custom classes - it can be any class, literally
  175 +final user = Rx<User>();
  176 +```
  177 +
  178 +3 - Cách tối ưu nhất, thêm **`.obs`**`value` :
  179 +
  180 +``` dart
  181 +final name = ''.obs;
  182 +final isLogged = false.obs;
  183 +final count = 0.obs;
  184 +final balance = 0.0.obs;
  185 +final number = 0.obs;
  186 +final items = <String>[].obs;
  187 +final myMap = <String, int>{}.obs;
  188 +
  189 +// Custom classes - it can be any class, literally
  190 +final user = User().obs;
  191 +```
  192 +
  193 +##### Thât dễ khi có reactive state.
  194 +
  195 +Như chúng ta biết, _Dart_ đang hướng tới _null safety_.
  196 +Để chuẩn bị, từ bây giờ, bạn phải luôn bắt đầu các biến _Rx_ của mình bằng một **initial value**.
  197 +
  198 +> Transforming a variable into an _observable_ + _initial value_ with **GetX** is the simplest, and most practical approach.
  199 +
  200 +Theo đúng nghĩa đen, bạn sẽ thêm một "` .obs` "vào cuối biến của mình và **vậy thôi người ơi~**, bạn đã làm cho nó có thể quan sát được, và `.value` của nó sẽ là _initial value_).
  201 +
  202 +### Sử dụng values trong View
  203 +
  204 +``` dart
  205 +// controller file
  206 +final count1 = 0.obs;
  207 +final count2 = 0.obs;
  208 +int get sum => count1.value + count2.value;
  209 +```
  210 +
  211 +``` dart
  212 +// view file
  213 +GetX<Controller>(
  214 + builder: (controller) {
  215 + print("count 1 rebuild");
  216 + return Text('${controller.count1.value}');
  217 + },
  218 +),
  219 +GetX<Controller>(
  220 + builder: (controller) {
  221 + print("count 2 rebuild");
  222 + return Text('${controller.count2.value}');
  223 + },
  224 +),
  225 +GetX<Controller>(
  226 + builder: (controller) {
  227 + print("count 3 rebuild");
  228 + return Text('${controller.sum}');
  229 + },
  230 +),
  231 +```
  232 +
  233 +Nếu chúng ta cộng `count1.value++` , nó sẽ in:
  234 +
  235 +* `count 1 rebuild`
  236 +
  237 +* `count 3 rebuild`
  238 +
  239 +bởi vì `count1` có giá trị là` 1` và `1 + 0 = 1`, thay đổi giá trị getter` sum`.
  240 +
  241 +Nếu ta thay đổi `count2.value++` , nó sẽ in:
  242 +
  243 +* `count 2 rebuild`
  244 +
  245 +* `count 3 rebuild`
  246 +
  247 +bởi vì `count2.value` đã thay đổi, và kết quả của` sum` bây giờ là `2`.
  248 +
  249 +* LƯU Ý: Theo mặc định, event đầu tiên sẽ xây dựng lại widget con, ngay cả khi nó là cùng một `giá trị`.
  250 +
  251 +Hành vi này tồn tại do các biến Boolean.
  252 +
  253 +Ví dụ, bạn code thế này:
  254 +
  255 +``` dart
  256 +var isLogged = false.obs;
  257 +```
  258 +
  259 +Và sau đó, bạn đã kiểm tra xem người dùng có "đăng nhập" để kích hoạt event trong `ever` không.
  260 +
  261 +``` dart
  262 +@override
  263 +onInit(){
  264 + ever(isLogged, fireRoute);
  265 + isLogged.value = await Preferences.hasToken();
  266 +}
  267 +
  268 +fireRoute(logged) {
  269 + if (logged) {
  270 + Get.off(Home());
  271 + } else {
  272 + Get.off(Login());
  273 + }
  274 +}
  275 +```
  276 +
  277 +nếu `hasToken` là` false`, sẽ không có thay đổi thành `isLogged`, vì vậy `ever ()` sẽ không bao giờ được gọi.
  278 +Để tránh loại hành vi này, thay đổi đầu tiên đối với _observable_ sẽ luôn kích hoạt một event,
  279 +ngay cả khi nó chứa cùng một `.value`.
  280 +
  281 +Bạn có thể xóa hành vi này nếu muốn, bằng cách sử dụng:
  282 + `isLogged.firstRebuild = false;`
  283 +
  284 +### Điều kiện để tái tạo lại
  285 +
  286 +Ngoài ra, Get cung cấp khả năng kiểm soát state đã được tinh chỉnh. Bạn có thể điều kiện một event (chẳng hạn như thêm một đối tượng vào danh sách), với một điều kiện nhất định.
  287 +
  288 +``` dart
  289 +// First parameter: condition, must return true or false.
  290 +// Second parameter: the new value to apply if the condition is true.
  291 +list.addIf(item < limit, item);
  292 +```
  293 +
  294 +Không có decoration, không có trình tạo mã, không có phức tạp hóa vấn đề: smile:
  295 +
  296 +Bạn có biết ứng dụng counter của Flutter không? Class controller của bạn có thể trông giống như sau:
  297 +
  298 +``` dart
  299 +class CountController extends GetxController {
  300 + final count = 0.obs;
  301 +}
  302 +```
  303 +
  304 +Đơn giản hơn:
  305 +
  306 +``` dart
  307 +controller.count.value++
  308 +```
  309 +
  310 +Bạn có thể cập nhật counter trong UI của mình, bất kể nó được lưu trữ ở đâu.
  311 +
  312 +### Nơi .obs có thể dùng
  313 +
  314 +Bạn có thể biến đổi bất cứ thứ gì trên obs. Đây là hai cách để làm điều đó:
  315 +
  316 +* Bạn có thể chuyển đổi các giá trị class của mình thành obs
  317 +
  318 +``` dart
  319 +class RxUser {
  320 + final name = "Camila".obs;
  321 + final age = 18.obs;
  322 +}
  323 +```
  324 +
  325 +* hoặc bạn có thể biến cả 1 class thành observable
  326 +
  327 +``` dart
  328 +class User {
  329 + User({String name, int age});
  330 + var name;
  331 + var age;
  332 +}
  333 +
  334 +// when instantianting:
  335 +final user = User(name: "Camila", age: 18).obs;
  336 +```
  337 +
  338 +### Chí ú về Lists
  339 +
  340 +List hoàn toàn có thể quan sát được cũng như các đối tượng bên trong nó. Bằng cách đó, nếu bạn thêm một giá trị vào danh sách, nó sẽ tự động xây dựng lại các widget con sử dụng nó.
  341 +
  342 +Bạn cũng không cần phải sử dụng ".value" với các danh sách, api phi tiêu tuyệt vời đã cho phép chúng tôi loại bỏ điều đó.
  343 +Tiếc thay, các kiểu nguyên thủy như String và int không thể được mở rộng, khiến việc sử dụng .value là bắt buộc, nhưng điều đó sẽ không thành vấn đề nếu bạn làm việc với getters và setters cho những thứ này.
  344 +
  345 +``` dart
  346 +// On the controller
  347 +final String title = 'User Info:'.obs
  348 +final list = List<User>().obs;
  349 +
  350 +// on the view
  351 +Text(controller.title.value), // String need to have .value in front of it
  352 +ListView.builder (
  353 + itemCount: controller.list.length // lists don't need it
  354 +)
  355 +```
  356 +
  357 +Khi bạn đang làm cho các class của riêng mình có thể quan sát được, có một cách khác để cập nhật chúng:
  358 +
  359 +``` dart
  360 +// on the model file
  361 +// we are going to make the entire class observable instead of each attribute
  362 +class User() {
  363 + User({this.name = '', this.age = 0});
  364 + String name;
  365 + int age;
  366 +}
  367 +
  368 +// on the controller file
  369 +final user = User().obs;
  370 +// when you need to update the user variable:
  371 +user.update( (user) { // this parameter is the class itself that you want to update
  372 +user.name = 'Jonny';
  373 +user.age = 18;
  374 +});
  375 +// an alternative way of update the user variable:
  376 +user(User(name: 'João', age: 35));
  377 +
  378 +// on view:
  379 +Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}"))
  380 +// you can also access the model values without the .value:
  381 +user().name; // notice that is the user variable, not the class (variable has lowercase u)
  382 +```
  383 +
  384 +Bạn không cần phải làm việc với các bộ nếu bạn không muốn. bạn có thể sử dụng api "assign" và "assignAll".
  385 +Api "assign" sẽ xóa danh sách của bạn và thêm một đối tượng duy nhất mà bạn muốn bắt đầu ở đó.
  386 +Api "allowAll" sẽ xóa danh sách hiện có và thêm bất kỳ đối tượng có thể lặp lại nào mà bạn đưa vào đó.
  387 +
  388 +### Tại sao tôi phải dùng .value
  389 +
  390 +Chúng ta có thể loại bỏ việc sử dụng 'value' đối với `String` và` int` bằng một trình tạo mã và decoration đơn giản, nhưng mục đích của thư viện này chính là tránh các dependency bên ngoài. Chúng tôi muốn cung cấp một môi trường sẵn sàng cho việc lập trình, liên quan đến các yếu tố cần thiết (quản lý các route, dependency và state), theo cách đơn giản, nhẹ và hiệu quả mà không cần gói bên ngoài.
  391 +
  392 +Theo nghĩa đen, bạn có thể thêm 3 chữ cái vào pubspec (get) của mình và dấu hai chấm và bắt đầu lập trình. Tất cả các giải pháp được bao gồm theo mặc định, từ quản lý route đến quản lý state, nhằm mục đích dễ dàng, năng suất và hiệu suất.
  393 +
  394 +Tổng trọng lượng của thư viện này ít hơn của một trình quản lý state duy nhất, mặc dù nó là một giải pháp hoàn chỉnh và đó là những gì bạn phải hiểu.
  395 +
  396 +Nếu bạn bị làm phiền bởi `.value`, và giống như một trình tạo mã, MobX là một giải pháp thay thế tuyệt vời và bạn có thể sử dụng nó cùng với Get. Đối với những người muốn thêm một gói dependency duy nhất vào pubspec và bắt đầu lập trình mà không cần lo lắng về phiên bản của gói không tương thích với gói khác hoặc nếu lỗi cập nhật state đến từ trình quản lý state hoặc dependency, hoặc vẫn không muốn lo lắng về sự sẵn có của controller, cho dù theo nghĩa đen là "chỉ là lập trình", GetX là lựa chọn hoàn hảo.
  397 +
  398 +Nếu bạn không gặp vấn đề gì với trình tạo mã MobX hoặc không gặp vấn đề gì với bảng soạn sẵn BLoC, bạn có thể chỉ cần sử dụng Get cho các route và quên rằng nó có trình quản lý state. Get SEM và RSM ra đời không cần thiết, công ty của tôi có một dự án với hơn 90 controller và trình tạo mã chỉ mất hơn 30 phút để hoàn thành nhiệm vụ của nó sau khi Flutter Clean trên một máy khá tốt, nếu dự án của bạn có 5, 10, 15 controller, bất kỳ nhà quản lý state sẽ cung cấp cho bạn tốt. Nếu bạn có một dự án lớn đến mức ngớ ngẩn và trình tạo mã là một vấn đề đối với bạn, thì bạn đã được trao giải pháp này.
  399 +
  400 +Rõ ràng, nếu ai đó muốn đóng góp vào dự án và tạo trình tạo mã, hoặc thứ gì đó tương tự, tôi sẽ liên kết trong readme này như một giải pháp thay thế, nhu cầu của tôi không phải là nhu cầu của tất cả các nhà phát triển, nhưng ý tôi là thế, đã có những giải pháp tốt đã làm được điều đó, như MobX.
  401 +
  402 +### Obx()
  403 +
  404 +Nhập vào Get bằng cách sử dụng Bindings là không cần thiết. bạn có thể sử dụng widget Obx thay vì GetX, widget chỉ nhận được chức năng ẩn danh tạo widget.
  405 +Rõ ràng, nếu bạn không sử dụng một kiểu, bạn sẽ cần phải có một phiên bản của controller để sử dụng các biến hoặc sử dụng `Get.find <Controller> ()` .value hoặc Controller.to.value để truy xuất giá trị .
  406 +
  407 +### Workers
  408 +
  409 +Workers sẽ hỗ trợ bạn, kích hoạt các lệnh gọi lại cụ thể khi một event xảy ra.
  410 +
  411 +``` dart
  412 +/// Called every time `count1` changes.
  413 +ever(count1, (_) => print("$_ has been changed"));
  414 +
  415 +/// Called only first time the variable $_ is changed
  416 +once(count1, (_) => print("$_ was changed once"));
  417 +
  418 +/// Anti DDos - Called every time the user stops typing for 1 second, for example.
  419 +debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1));
  420 +
  421 +/// Ignore all changes within 1 second.
  422 +interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
  423 +```
  424 +
  425 +Tất cả các workers (except `debounce` ) có `condition` tham số được đặt tên, mà có thể là loại `bool` hoặc lệnh gọi lại trả về một `bool` .
  426 +`condition` này mô tả khi `callback` kích hoạt.
  427 +
  428 +Tất cả các workers đều trả về trường hợp `Worker`, mà bạn có thể đóng ( thông qua `dispose()` ) của worker.
  429 +
  430 +
  431 +* **`ever`**
  432 +
  433 + được gọi mỗi khi biến _Rx_ tạo ra một giá trị mới.
  434 +
  435 +* **`everAll`**
  436 +
  437 +Giống như `ever`, nhưng nó có một` List` gồm các giá trị _Rx_ Được gọi mỗi khi biến của nó bị thay đổi. Chỉ vậy thôi người ơi~ 😊
  438 +
  439 +* **`once`**
  440 +
  441 +'once' chỉ được gọi lần đầu tiên biến được thay đổi.
  442 +
  443 +* **`debounce`**
  444 +
  445 +'debounce' rất hữu ích trong các hàm tìm kiếm, nơi bạn chỉ muốn API được gọi khi người dùng nhập xong. Nếu người dùng nhập "Kaiser", bạn sẽ có 6 tìm kiếm trong các API, theo ký tự K, a, i, s, e và r. Với Get, điều này không xảy ra, bởi vì bạn sẽ có một Worker "debounce" sẽ chỉ được kích hoạt khi kết thúc nhập.
  446 +
  447 +* **`interval`**
  448 +
  449 +'interval' khác với debounce. Debounce xảy ra nếu người dùng thực hiện 1000 thay đổi đối với một biến trong vòng 1 giây, y sẽ chỉ gửi biến cuối cùng sau bộ hẹn giờ quy định (mặc định là 800 mili giây). Thay vào đó, interval sẽ bỏ qua tất cả các hành động của người dùng trong interval quy định. Nếu bạn gửi event trong 1 phút, 1000 mỗi giây, tính năng gỡ lỗi sẽ chỉ gửi cho bạn event cuối cùng, khi người dùng ngừng phân chia event. interval sẽ phân phối các event mỗi giây và nếu được đặt thành 3 giây, nó sẽ phân phối 20 event trong phút đó. Điều này được khuyến nghị để tránh lạm dụng, trong các chức năng mà người dùng có thể nhanh chóng nhấp vào một thứ gì đó và có được một số lợi thế (hãy tưởng tượng rằng người dùng có thể kiếm được xu bằng cách nhấp vào thứ gì đó, nếu y nhấp 300 lần trong cùng một phút, y sẽ có 300 xu, bằng cách sử dụng interval, bạn có thể đặt khung thời gian trong 3 giây, và thậm chí sau đó nhấp vào 300 hoặc một nghìn lần, tối đa y sẽ nhận được trong 1 phút sẽ là 20 xu, nhấp 300 hoặc 1 triệu lần). Việc gỡ lỗi này phù hợp cho việc chống DDos, cho các chức năng như tìm kiếm trong đó mỗi thay đổi đối với onChange sẽ gây ra một truy vấn tới api của bạn. Debounce sẽ đợi người dùng ngừng nhập tên để thực hiện yêu cầu. Nếu nó được sử dụng trong kịch bản đồng xu được đề cập ở trên, người dùng sẽ chỉ giành được 1 đồng xu, bởi vì nó chỉ được thực thi, khi người dùng "tạm dừng" trong thời gian đã thiết lập.
  450 +
  451 +* CHÍ Ú: Workers phải luôn được sử dụng khi khởi động Controller hoặc Class, vì vậy nó phải luôn ở trên onInit (được khuyến nghị), phương thức khởi tạo Class hoặc initState của StatefulWidget (phương pháp này không được khuyến khích trong hầu hết các trường hợp, nhưng nó không nên có hiệu ứng phụ nào khác).
  452 +
  453 +## Quản lý State đơn giản
  454 +
  455 +Get có một trình quản lý state cực kỳ nhẹ và dễ dàng, không sử dụng ChangeNotifier, sẽ đáp ứng nhu cầu đặc biệt cho những người mới sử dụng Flutter và sẽ không gây ra sự cố cho các ứng dụng lớn.
  456 +
  457 +GetBuilder nhắm chính xác vào việc kiểm soát nhiều state. Hãy tưởng tượng rằng bạn đã thêm 30 sản phẩm vào giỏ hàng, bạn nhấp vào xóa một sản phẩm, đồng thời danh sách được cập nhật, giá được cập nhật và huy hiệu trong giỏ hàng được cập nhật thành số lượng nhỏ hơn. Kiểu tiếp cận này khiến GetBuilder trở thành kẻ giết người, bởi vì nó nhóm các state và thay đổi tất cả chúng cùng một lúc mà không có bất kỳ "logic tính toán" nào cho điều đó. GetBuilder được tạo ra với loại tình huống này, vì để thay đổi state tạm thời, bạn có thể sử dụng setState và bạn sẽ không cần trình quản lý state cho việc này.
  458 +
  459 +Bằng cách đó, nếu bạn muốn một controller riêng lẻ, bạn có thể gán ID cho controller đó hoặc sử dụng GetX. Điều này là tùy thuộc vào bạn, hãy nhớ rằng bạn càng có nhiều widget "riêng lẻ" thì hiệu suất của GetX càng nổi bật, trong khi hiệu suất của GetBuilder phải vượt trội hơn khi có nhiều thay đổi state.
  460 +
  461 +### Lợi thế
  462 +
  463 +1. Chỉ cập nhật các widget được yêu cầu.
  464 +
  465 +2. Không sử dụng changeNotifier, đó là trình quản lý state sử dụng ít bộ nhớ hơn (gần như bằng 0mb).
  466 +
  467 +3. Quên StatefulWidget! Với Get, bạn sẽ không bao giờ cần đến nó. Với các trình quản lý state khác, bạn có thể sẽ phải sử dụng StatefulWidget để lấy phiên bản của Provider, BLoC, MobX, v.v. Nhưng bạn đã bao giờ nghĩ rằng AppBar, Scaffole và hầu hết các widget trong class của bạn là stateless? Vậy tại sao phải lưu state của toàn bộ class, nếu bạn chỉ có thể lưu state của Widget là stateful? Get giải quyết được điều đó bằng cách tạo một class Stateless, làm cho mọi thứ trở nên vô trạng. Nếu bạn cần cập nhật một thành phần riêng lẻ, hãy bọc nó bằng GetBuilder và state của nó sẽ được duy trì.
  468 +
  469 +4. Tái cơ cấu cho dự án của bạn xanh, sạch và đẹp! Controller không được nằm trong UI của bạn, hãy đặt TextEditController của bạn hoặc bất kỳ controller nào bạn sử dụng trong class Controller của mình.
  470 +
  471 +5. Bạn có cần kích hoạt event để cập nhật widget con ngay khi nó được hiển thị không? GetBuilder có thuộc tính "initState", giống như StatefulWidget và bạn có thể gọi các event từ controller của mình, trực tiếp từ nó, không có thêm event nào được đặt trong initState của bạn.
  472 +
  473 +6. Bạn có cần phải kích hoạt một hành động như đóng streams, hẹn giờ, v.v. không? GetBuilder cũng có dispose property, nơi bạn có thể gọi các event ngay khi widget đó bị phá hủy.
  474 +
  475 +7. Chỉ sử dụng các streams nếu cần thiết. Bạn có thể sử dụng StreamControllers bên trong controller của mình một cách bình thường và sử dụng StreamBuilder cũng bình thường, nhưng hãy nhớ rằng, một streams tiêu thụ bộ nhớ một kha khá, lập trình phản ứng rất đẹp, nhưng bạn không nên lạm dụng nó. 30 streams mở cùng lúc có thể tệ hơn changeNotifier (và changeNotifier đã rất là tệ).
  476 +
  477 +8. Cập nhật các widgets mà không tốn ram. Chỉ lưu trữ ID người tạo GetBuilder và cập nhật GetBuilder đó khi cần thiết. Mức tiêu thụ bộ nhớ của get ID trong bộ nhớ là rất thấp ngay cả đối với hàng nghìn GetBuilders. Khi bạn tạo GetBuilder mới, bạn thực sự đang chia sẻ state GetBuilder có ID người tạo. Một state mới không được tạo cho mỗi GetBuilder, giúp tiết kiệm RẤT NHIỀU ram cho các ứng dụng lớn. Về cơ bản, ứng dụng của bạn sẽ hoàn toàn là Không state và một số ít Tiện ích sẽ có state (trong GetBuilder) sẽ có một state duy nhất, và do đó cập nhật một sẽ cập nhật tất cả. Nhà nước chỉ là một.
  478 +
  479 +9. Get là toàn trí và trong hầu hết các trường hợp, nó biết chính xác thời gian để lấy controller ra khỏi bộ nhớ. Bạn không nên lo lắng về việc khi nào nên vứt bỏ controller, Get biết thời điểm tốt nhất để thực hiện việc này.
  480 +
  481 +### Sử dụng
  482 +
  483 +``` dart
  484 +// Create controller class and extends GetxController
  485 +class Controller extends GetxController {
  486 + int counter = 0;
  487 + void increment() {
  488 + counter++;
  489 + update(); // use update() to update counter variable on UI when increment be called
  490 + }
  491 +}
  492 +// On your Stateless/Stateful class, use GetBuilder to update Text when increment be called
  493 +GetBuilder<Controller>(
  494 + init: Controller(), // INIT IT ONLY THE FIRST TIME
  495 + builder: (_) => Text(
  496 + '${_.counter}',
  497 + ),
  498 +)
  499 +//Initialize your controller only the first time. The second time you are using ReBuilder for the same controller, do not use it again. Your controller will be automatically removed from memory as soon as the widget that marked it as 'init' is deployed. You don't have to worry about that, Get will do it automatically, just make sure you don't start the same controller twice.
  500 +```
  501 +
  502 +**OK, giải thích xong rồi!**
  503 +
  504 +* Bạn đã học cách quản lý state với Get.
  505 +
  506 +* Lưu ý: Bạn có thể muốn một tổ chức lớn hơn và không sử dụng thuộc tính init. Vì vậy, bạn có thể tạo một class và mở rộng class Bindings và trong đó đề cập đến các controller sẽ được tạo trong route đó. Khi đó các Controllers sẽ không được tạo, ngược lại, đây chỉ là một câu lệnh, để lần đầu sử dụng Controller, Get sẽ biết cần tìm ở đâu. Get sẽ vẫn là lazyLoad và sẽ tiếp tục loại bỏ Controller khi chúng không còn cần thiết nữa. Hãy xem ví dụ pub.dev để xem nó hoạt động như thế nào.
  507 +
  508 +Nếu bạn điều hướng nhiều route và cần dữ liệu trong controller đã sử dụng trước đó, bạn chỉ cần sử dụng GetBuilder Again (không có init):
  509 +
  510 +``` dart
  511 +class OtherClass extends StatelessWidget {
  512 + @override
  513 + Widget build(BuildContext context) {
  514 + return Scaffold(
  515 + body: Center(
  516 + child: GetBuilder<Controller>(
  517 + builder: (s) => Text('${s.counter}'),
  518 + ),
  519 + ),
  520 + );
  521 + }
  522 +
  523 +```
  524 +
  525 +Nếu bạn cần sử dụng controller của mình ở nhiều nơi khác và bên ngoài GetBuilder, chỉ cần tạo quyền truy cập vào controller của bạn và có nó một cách dễ dàng. (hoặc sử dụng `Get.find <Controller> ()`)
  526 +
  527 +``` dart
  528 +class Controller extends GetxController {
  529 +
  530 + /// You do not need that. I recommend using it just for ease of syntax.
  531 + /// with static method: Controller.to.increment();
  532 + /// with no static method: Get.find<Controller>().increment();
  533 + /// There is no difference in performance, nor any side effect of using either syntax. Only one does not need the type, and the other the IDE will autocomplete it.
  534 + static Controller get to => Get.find(); // add this line
  535 +
  536 + int counter = 0;
  537 + void increment() {
  538 + counter++;
  539 + update();
  540 + }
  541 +}
  542 +```
  543 +
  544 +Sau đó, truy cập thẳng vào controller của bạn:
  545 +
  546 +``` dart
  547 +FloatingActionButton(
  548 + onPressed: () {
  549 + Controller.to.increment(),
  550 + } // This is incredibly simple!
  551 + child: Text("${Controller.to.counter}"),
  552 +),
  553 +```
  554 +
  555 +Khi bạn nhấn FloatingActionButton, tất cả các widget đang lắng nghe biến 'counter' sẽ được cập nhật tự động.
  556 +
  557 +### Cách GetX sử dụng controllers
  558 +
  559 +Ví dụ:
  560 +
  561 + `Class a => Class B (has controller X) => Class C (has controller X)`
  562 +
  563 +Trong class A, controller chưa có trong bộ nhớ, vì bạn chưa sử dụng nó (Get là lazyLoad). Trong class B, bạn đã sử dụng controller và nó đã vào bộ nhớ. Trong class C, bạn đã sử dụng cùng một controller như trong class B, Get sẽ chia sẻ state của controller B với controller C, và controller tương tự vẫn còn trong bộ nhớ. Nếu bạn đóng màn hình C và màn hình B, Get sẽ tự động lấy controller X ra khỏi bộ nhớ và giải phóng tài nguyên, vì Class A không sử dụng controller. Nếu bạn điều hướng đến B một lần nữa, controller X sẽ nhập lại bộ nhớ, nếu thay vì đi đến class C, bạn quay lại class A một lần nữa, Get sẽ đưa controller ra khỏi bộ nhớ theo cách tương tự. Nếu class C không sử dụng controller và bạn đã lấy class B ra khỏi bộ nhớ, thì sẽ không có class nào sử dụng controller X và tương tự như vậy, nó sẽ bị loại bỏ. Ngoại lệ duy nhất có thể gây rắc rối với Get là nếu bạn xóa B khỏi route một cách bất ngờ và cố gắng sử dụng controller trong C. Trong trường hợp này, ID người tạo của controller ở B đã bị xóa và Get được lập trình để xóa nó khỏi bộ nhớ mọi controller không có ID người tạo. Nếu bạn dự định làm điều này, hãy thêm flag "autoRemove: false" vào GetBuilder của class B và sử dụng adoptID = true trong GetBuilder của class C.
  564 +
  565 +### Không cần StatefulWidget nữa!
  566 +
  567 +Sử dụng StatefulWidgets có nghĩa là lưu trữ state của toàn bộ màn hình một cách không cần thiết, ngay cả khi bạn cần xây dựng lại một cách tối thiểu widget, bạn sẽ nhúng nó vào Consumer / Observer / BlocProvider / GetBuilder / GetX / Obx, đây sẽ là một StatefulWidget khác.
  568 +Class StatefulWidget là một class lớn hơn StatelessWidget, class này sẽ phân bổ nhiều RAM hơn và điều này có thể không tạo ra sự khác biệt đáng kể giữa một hoặc hai class, nhưng chắc chắn nó sẽ làm được khi bạn có 100 class trong số chúng!
  569 +Trừ khi bạn cần sử dụng một mixin, như TickerProviderStateMixin, thì việc sử dụng StatefulWidget với Get là hoàn toàn không cần thiết.
  570 +
  571 +Bạn có thể gọi trực tiếp tất cả các phương thức của StatefulWidget từ GetBuilder.
  572 +Nếu bạn cần gọi phương thức initState () hoặc dispose () chẳng hạn, bạn có thể gọi chúng trực tiếp;
  573 +
  574 +``` dart
  575 +GetBuilder<Controller>(
  576 + initState: (_) => Controller.to.fetchApi(),
  577 + dispose: (_) => Controller.to.closeStreams(),
  578 + builder: (s) => Text('${s.username}'),
  579 +),
  580 +```
  581 +
  582 +Một cách tiếp cận tốt hơn nhiều so với cách này là sử dụng phương thức onInit () và onClose () trực tiếp từ controller của bạn.
  583 +
  584 +``` dart
  585 +@override
  586 +void onInit() {
  587 + fetchApi();
  588 + super.onInit();
  589 +}
  590 +```
  591 +
  592 +* CHÍ Ú: Nếu bạn muốn bắt đầu một phương thức tại thời điểm controller được gọi lần đầu tiên, bạn KHÔNG CẦN sử dụng các hàm tạo cho việc này, trên thực tế, bằng cách sử dụng gói hướng hiệu suất như Get, điều này không phù hợp với thực tiễn xấu, bởi vì nó lệch khỏi logic trong đó controller được tạo hoặc chỉ định (nếu bạn tạo một phiên bản của controller này, hàm tạo sẽ được gọi ngay lập tức, bạn sẽ điền controller trước khi nó được sử dụng, bạn đang cấp phát bộ nhớ mà không sử dụng nó , điều này chắc chắn làm hỏng các nguyên tắc của thư viện này). Các phương thức onInit(); và onClose(); được tạo ra cho mục đích này, chúng sẽ được gọi khi Controller được tạo hoặc được sử dụng lần đầu tiên, tùy thuộc vào việc bạn có đang sử dụng Get.lazyPut hay không. Ví dụ: nếu bạn muốn thực hiện lệnh gọi tới API của mình để điền dữ liệu, bạn có thể quên phương thức cũ của initState / dispose, chỉ cần bắt đầu lệnh gọi tới api trong onInit. Nếu bạn cần thực thi bất kỳ lệnh nào, như đóng streams, hãy sử dụng onClose() cho việc đó.
  593 +
  594 +### Tại sao GetX tồn tại?
  595 +
  596 +Mục đích của gói này chính xác là cung cấp cho bạn một giải pháp hoàn chỉnh để điều hướng các route, quản lý các dependency và state, sử dụng các dependency ít nhất có thể, với mức độ tách biệt cao. Nhận tất cả các API Flutter cấp cao và cấp thấp trong chính nó, để đảm bảo rằng bạn làm việc với ít khớp nối nhất có thể. Chúng tôi tập trung mọi thứ trong một gói duy nhất, để đảm bảo rằng bạn không có bất kỳ loại khớp nối nào trong dự án của mình. Bằng cách đó, bạn có thể chỉ đặt các widget trong chế độ xem của mình và để phần của nhóm làm việc với logic nghiệp vụ tự do làm việc với logic nghiệp vụ độc lập với View. Điều này cung cấp một môi trường làm việc sạch hơn nhiều, để một phần nhóm của bạn chỉ hoạt động với các widget mà không phải lo lắng về việc gửi dữ liệu đến controller của bạn và một phần nhóm của bạn chỉ làm việc với logic nghiệp vụ trong phạm vi bề rộng của nó mà không dependency vào bất kỳ yếu tố View.
  597 +
  598 +Vì vậy, để đơn giản hóa điều này:
  599 +Bạn không cần gọi các phương thức trong initState và gửi chúng theo tham số đến controller của mình, cũng như không sử dụng phương thức khởi tạo controller cho việc đó, bạn có phương thức onInit() được gọi vào đúng thời điểm để bạn khởi động các dịch vụ của mình.
  600 +Bạn không cần phải gọi thiết bị, bạn có phương thức onClose() sẽ được gọi vào thời điểm chính xác khi controller của bạn không còn cần thiết nữa và sẽ bị xóa khỏi bộ nhớ. Bằng cách đó, chỉ để lại chế độ xem cho các widget, tránh bất kỳ loại logic nghiệp vụ nào từ nó.
  601 +
  602 +Đừng gọi một phương thức vứt bỏ bên trong GetxController, nó sẽ không làm được gì cả, hãy nhớ rằng controller không phải là một Widget, bạn không nên "vứt bỏ" nó, và nó sẽ được Get tự động và thông minh xóa khỏi bộ nhớ. Nếu bạn đã sử dụng bất kỳ streams nào trên đó và muốn đóng streams đó, chỉ cần chèn streams đó vào phương thức đóng. Thí dụ:
  603 +
  604 +``` dart
  605 +class Controller extends GetxController {
  606 + StreamController<User> user = StreamController<User>();
  607 + StreamController<String> name = StreamController<String>();
  608 +
  609 + /// close stream = onClose method, not dispose.
  610 + @override
  611 + void onClose() {
  612 + user.close();
  613 + name.close();
  614 + super.onClose();
  615 + }
  616 +}
  617 +```
  618 +
  619 +Vòng đời của controller:
  620 +
  621 +* onInit() nơi nó được tạo.
  622 +* onClose() nơi nó được đóng để thực hiện bất kỳ thay đổi nào nhằm chuẩn bị cho phương thức xóa
  623 +* deleted: bạn không có quyền truy cập vào API này vì nó sẽ xóa controller khỏi bộ nhớ theo đúng nghĩa đen. Nó được xóa theo đúng nghĩa đen, mà không để lại bất kỳ dấu vết nào.
  624 +
  625 +### Cách sử dụng khác
  626 +
  627 +Bạn có thể sử dụng phiên bản Controller trực tiếp trên giá trị GetBuilder:
  628 +
  629 +``` dart
  630 +GetBuilder<Controller>(
  631 + init: Controller(),
  632 + builder: (value) => Text(
  633 + '${value.counter}', //here
  634 + ),
  635 +),
  636 +```
  637 +
  638 +Bạn cũng có thể cần một phiên bản của controller bên ngoài GetBuilder và bạn có thể sử dụng các phương pháp này để đạt được điều này:
  639 +
  640 +``` dart
  641 +class Controller extends GetxController {
  642 + static Controller get to => Get.find();
  643 +[...]
  644 +}
  645 +// on you view:
  646 +GetBuilder<Controller>(
  647 + init: Controller(), // use it only first time on each controller
  648 + builder: (_) => Text(
  649 + '${Controller.to.counter}', //here
  650 + )
  651 +),
  652 +```
  653 +
  654 +or
  655 +
  656 +``` dart
  657 +class Controller extends GetxController {
  658 + // static Controller get to => Get.find(); // with no static get
  659 +[...]
  660 +}
  661 +// on stateful/stateless class
  662 +GetBuilder<Controller>(
  663 + init: Controller(), // use it only first time on each controller
  664 + builder: (_) => Text(
  665 + '${Get.find<Controller>().counter}', //here
  666 + ),
  667 +),
  668 +```
  669 +
  670 +* Bạn có thể sử dụng các phương pháp tiếp cận "không chuẩn" để thực hiện việc này. Nếu bạn đang sử dụng một số trình quản lý dependency khác, như get_it, modular, v.v. và chỉ muốn cung cấp phiên bản controller, bạn có thể thực hiện điều này:
  671 +
  672 +``` dart
  673 +Controller controller = Controller();
  674 +[...]
  675 +GetBuilder<Controller>(
  676 + init: controller, //here
  677 + builder: (_) => Text(
  678 + '${controller.counter}', // here
  679 + ),
  680 +),
  681 +
  682 +```
  683 +
  684 +### IDs độc nhất
  685 +
  686 +Nếu bạn muốn tinh chỉnh kiểm soát cập nhật của widget con với GetBuilder, bạn có thể gán cho chúng các ID độc:
  687 +
  688 +``` dart
  689 +GetBuilder<Controller>(
  690 + id: 'text'
  691 + init: Controller(), // use it only first time on each controller
  692 + builder: (_) => Text(
  693 + '${Get.find<Controller>().counter}', //here
  694 + ),
  695 +),
  696 +```
  697 +
  698 +Và cập nhật nó vào biểu mẫu này:
  699 +
  700 +``` dart
  701 +update(['text']);
  702 +```
  703 +
  704 +Bạn cũng có thể áp đặt các điều kiện cho bản cập nhật:
  705 +
  706 +``` dart
  707 +update(['text'], counter < 10);
  708 +```
  709 +
  710 +GetX thực hiện điều này tự động và chỉ cấu trúc lại widget con sử dụng biến chính xác đã được thay đổi, nếu bạn thay đổi một biến thành giống với biến trước đó và điều đó không ngụ ý thay đổi state, GetX sẽ không xây dựng lại widget con để tiết kiệm bộ nhớ và Chu kỳ CPU ( 3 đang được hiển thị trên màn hình và bạn lại thay đổi biến thành 3. Trong hầu hết các trình quản lý state, điều này sẽ gây ra việc xây dựng lại mới, nhưng với GetX, widget sẽ chỉ được xây dựng lại, nếu trên thực tế state của nó đã thay đổi ).
  711 +
  712 +## Trộn hai trình quản lý state
  713 +
  714 +Một số người đã mở một yêu cầu tính năng, vì họ chỉ muốn sử dụng một loại biến phản ứng và cơ chế khác và cần chèn Obx vào GetBuilder cho việc này. Suy nghĩ về nó MixinBuilder đã được tạo ra. Nó cho phép cả những thay đổi phản ứng bằng cách thay đổi các biến ".obs" và cập nhật thủ công thông qua update(). Tuy nhiên, trong số 4 widget, nó là widget tiêu tốn nhiều tài nguyên nhất, vì ngoài việc có Subscription để nhận các event thay đổi từ con mình, nó còn đăng ký phương thức cập nhật của controller của mình.
  715 +
  716 +Việc mở rộng GetxController rất quan trọng, vì chúng có vòng đời và có thể "bắt đầu" và "kết thúc" các event trong các phương thức onInit() và onClose() của chúng. Bạn có thể sử dụng bất kỳ lớp nào cho việc này, nhưng tôi thực sự khuyên bạn nên sử dụng lớp GetxController để đặt các biến của bạn, cho dù chúng có thể quan sát được hay không.
  717 +
  718 +## StateMixin
  719 +
  720 +Một cách khác để xử lý state `UI` của bạn là sử dụng` StateMixin <T> `.
  721 +Để triển khai nó, hãy sử dụng dấu `với` để thêm` StateMixin <T> ` bộ điều khiển của bạn cho phép một mô hình T.
  722 +
  723 +``` dart
  724 +class Controller extends GetController with StateMixin<User>{}
  725 +```
  726 +
  727 +Phương thức `change()` thay đổi state bất cứ khi nào chúng ta muốn.
  728 +Chỉ cần truyền dữ liệu và state theo cách này:
  729 +
  730 +```dart
  731 +change(data, status: RxStatus.success());
  732 +```
  733 +
  734 +RxStatus cho phép các state này:
  735 +
  736 +``` dart
  737 +RxStatus.loading();
  738 +RxStatus.success();
  739 +RxStatus.empty();
  740 +RxStatus.error('message');
  741 +```
  742 +
  743 +Để diễn tả nó trên UI, sử dụng:
  744 +
  745 +```dart
  746 +class OtherClass extends GetView<Controller> {
  747 + @override
  748 + Widget build(BuildContext context) {
  749 + return Scaffold(
  750 +
  751 + body: controller.obx(
  752 + (state)=>Text(state.name),
  753 +
  754 + // here you can put your custom loading indicator, but
  755 + // by default would be Center(child:CircularProgressIndicator())
  756 + onLoading: CustomLoadingIndicator(),
  757 + onEmpty: Text('No data found'),
  758 +
  759 + // here also you can set your own error widget, but by
  760 + // default will be an Center(child:Text(error))
  761 + onError: (error)=>Text(error),
  762 + ),
  763 + );
  764 +}
  765 +```
  766 +
  767 +## GetBuilder vs GetX vs Obx vs MixinBuilder
  768 +
  769 +Trong một thập kỷ làm việc với lập trình, tôi đã có thể học được một số bài học quý giá.
  770 +
  771 +Lần đầu tiên tôi tiếp xúc với lập trình phản ứng là rất "Trời thần ơi, tuyệt vời ông mặt trời!" và trên thực tế, lập trình phản ứng là không thể tin được.
  772 +Tuy nhiên, nó không phải là thích hợp cho tất cả các trường hợp. Thông thường, tất cả những gì bạn cần là thay đổi state của 2 hoặc 3 widget cùng lúc, hoặc thay đổi state trong thời gian ngắn, trong trường hợp này, lập trình phản ứng không phải là xấu, nhưng nó không phù hợp.
  773 +
  774 +Lập trình phản ứng có mức tiêu thụ RAM cao hơn có thể được bù đắp bởi quy trình làm việc riêng lẻ, điều này sẽ đảm bảo rằng chỉ một widget con được xây dựng lại và khi cần thiết, nhưng tạo danh sách với 80 đối tượng, mỗi đối tượng có nhiều streams không phải là một ý kiến hay . Mở thanh kiểm tra phi tiêu và kiểm tra xem StreamBuilder tiêu thụ bao nhiêu và bạn sẽ hiểu những gì tôi đang cố gắng nói với bạn.
  775 +
  776 +Với ý nghĩ đó, tôi đã tạo trình quản lý state đơn giản. Nó đơn giản, và đó chính xác là những gì bạn cần ở nó: cập nhật state trong các khối theo cách đơn giản và tiết kiệm nhất.
  777 +
  778 +GetBuilder rất tiết kiệm RAM và khó có cách tiếp cận nào tiết kiệm hơn nó (ít nhất là tôi không thể tưởng tượng được, nếu đã tồn tại cách khác, vui lòng cho chúng tôi biết).
  779 +
  780 +Tuy nhiên, GetBuilder vẫn là một trình quản lý state cơ học, bạn cần phải gọi update () giống như bạn sẽ cần gọi tới Provider's InformListaries ().
  781 +
  782 +Có những tình huống khác mà lập trình phản ứng thực sự thú vị và nếu không dùng nó đồng nghĩa như đang phát minh lại cái bánh xe. Với suy nghĩ đó, GetX được tạo ra để cung cấp mọi thứ hiện đại và tiên tiến nhất trong một trình quản lý state. Nó chỉ cập nhật những gì cần thiết và khi cần thiết, nếu bạn gặp lỗi và gửi 300 state thay đổi đồng thời, GetX sẽ lọc và cập nhật màn hình chỉ khi state thực sự thay đổi.
  783 +
  784 +GetX vẫn tiết kiệm hơn bất kỳ trình quản lý state phản ứng nào khác, nhưng nó tiêu tốn nhiều RAM hơn GetBuilder một chút. Suy nghĩ về điều đó và hướng tới việc tiêu thụ tối đa tài nguyên mà Obx đã tạo ra. Không giống như GetX và GetBuilder, bạn sẽ không thể khởi tạo controller bên trong Obx, nó chỉ là một Widget với StreamSubscription nhận các event thay đổi từ con bạn, vậy thôi. Nó tiết kiệm hơn GetX, nhưng thua GetBuilder, điều được mong đợi, vì nó có tính phản ứng và GetBuilder có cách tiếp cận đơn giản nhất tồn tại, đó là lưu trữ hashCode của widget con và StateSetter của nó. Với Obx, bạn không cần phải viết loại controller của mình và bạn có thể nghe thấy sự thay đổi từ nhiều controller khác nhau, nhưng nó cần được khởi tạo trước đó, sử dụng phương pháp ví dụ ở đầu readme này hoặc sử dụng class Bindings.