Jonatas

prevent rx out controller of create memory leak

@@ -188,7 +188,7 @@ Get은 두가지 상태 관리자가 있습니다: 단순 상태관리자(GetBui @@ -188,7 +188,7 @@ Get은 두가지 상태 관리자가 있습니다: 단순 상태관리자(GetBui
188 - 각 변수에 대해 StreamBuilder를 만들 필요가 없습니다. 188 - 각 변수에 대해 StreamBuilder를 만들 필요가 없습니다.
189 - 각각의 상태(state)를 위한 클래스를 만들 필요가 없습니다. 189 - 각각의 상태(state)를 위한 클래스를 만들 필요가 없습니다.
190 - 초기값을 위한 get이 필요하지 않습니다. 190 - 초기값을 위한 get이 필요하지 않습니다.
191 -- 코드 생성기를 사용할 필요가 없스빈다. 191 +- 코드 생성기를 사용할 필요가 없습니다.
192 192
193 Get의 반응형 프로그램은 setState를 사용하는 것 만큼 쉽습니다. 193 Get의 반응형 프로그램은 setState를 사용하는 것 만큼 쉽습니다.
194 194
@@ -216,7 +216,7 @@ Obx(() => Text("${controller.name}")); @@ -216,7 +216,7 @@ Obx(() => Text("${controller.name}"));
216 216
217 ### 상태 관리에 대한 자세한 내용 217 ### 상태 관리에 대한 자세한 내용
218 218
219 -**상태 관리에 대한 자세한 설명은 [여기](./documentation/en_US/state_management.md)를 보십시오. 여기에서 더 많은 예제와 단순 상태 관리자와 반응형 상태 관리자의 차이점을 볼 수 있습니다.** 219 +**상태 관리에 대한 자세한 설명은 [여기](./documentation/kr_KO/state_management.md)를 보십시오. 여기에서 더 많은 예제와 단순 상태 관리자와 반응형 상태 관리자의 차이점을 볼 수 있습니다.**
220 220
221 GetX 능력에 대한 좋은 아이디어를 얻을 수 있습니다. 221 GetX 능력에 대한 좋은 아이디어를 얻을 수 있습니다.
222 222
@@ -916,6 +916,55 @@ user.update((value){ @@ -916,6 +916,55 @@ user.update((value){
916 916
917 print( user ); 917 print( user );
918 ``` 918 ```
  919 +## StateMixin
  920 +
  921 +Another way to handle your `UI` state is use the `StateMixin<T>` .
  922 +To implement it, use the `with` to add the `StateMixin<T>`
  923 +to your controller which allows a T model.
  924 +
  925 +``` dart
  926 +class Controller extends GetController with StateMixin<User>{}
  927 +```
  928 +
  929 +The `change()` method change the State whenever we want.
  930 +Just pass the data and the status in this way:
  931 +
  932 +```dart
  933 +change(data, status: RxStatus.success());
  934 +```
  935 +
  936 +RxStatus allow these status:
  937 +
  938 +``` dart
  939 +RxStatus.loading();
  940 +RxStatus.success();
  941 +RxStatus.empty();
  942 +RxStatus.error('message');
  943 +```
  944 +
  945 +To represent it in the UI, use:
  946 +
  947 +```dart
  948 +class OtherClass extends GetView<Controller> {
  949 + @override
  950 + Widget build(BuildContext context) {
  951 + return Scaffold(
  952 +
  953 + body: controller.obx(
  954 + (state)=>Text(state.name),
  955 +
  956 + // here you can put your custom loading indicator, but
  957 + // by default would be Center(child:CircularProgressIndicator())
  958 + onLoading: CustomLoadingIndicator(),
  959 + onEmpty: Text('No data found'),
  960 +
  961 + // here also you can set your own error widget, but by
  962 + // default will be an Center(child:Text(error))
  963 + onError: (error)=>Text(error),
  964 + ),
  965 + );
  966 +}
  967 +```
919 968
920 #### GetView 969 #### GetView
921 970
@@ -924,7 +973,7 @@ I love this Widget, is so simple, yet, so useful! @@ -924,7 +973,7 @@ I love this Widget, is so simple, yet, so useful!
924 Is a `const Stateless` Widget that has a getter `controller` for a registered `Controller`, that's all. 973 Is a `const Stateless` Widget that has a getter `controller` for a registered `Controller`, that's all.
925 974
926 ```dart 975 ```dart
927 - class AwesomeController extends GetxController { 976 + class AwesomeController extends GetController {
928 final String title = 'My Awesome View'; 977 final String title = 'My Awesome View';
929 } 978 }
930 979
@@ -1120,6 +1169,7 @@ Any contribution is welcome! @@ -1120,6 +1169,7 @@ Any contribution is welcome!
1120 1169
1121 ## Articles and videos 1170 ## Articles and videos
1122 1171
  1172 +- [Flutter Getx EcoSystem package for arabic people](https://www.youtube.com/playlist?list=PLV1fXIAyjeuZ6M8m56zajMUwu4uE3-SL0) - Tutorial by [Pesa Coder](https://github.com/UsamaElgendy).
1123 - [Dynamic Themes in 3 lines using GetX™](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Tutorial by [Rod Brown](https://github.com/RodBr). 1173 - [Dynamic Themes in 3 lines using GetX™](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Tutorial by [Rod Brown](https://github.com/RodBr).
1124 - [Complete GetX™ Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI) - Route management video by Amateur Coder. 1174 - [Complete GetX™ Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI) - Route management video by Amateur Coder.
1125 - [Complete GetX State Management](https://www.youtube.com/watch?v=CNpXbeI_slw) - State management video by Amateur Coder. 1175 - [Complete GetX State Management](https://www.youtube.com/watch?v=CNpXbeI_slw) - State management video by Amateur Coder.
@@ -1133,3 +1183,4 @@ Any contribution is welcome! @@ -1133,3 +1183,4 @@ Any contribution is welcome!
1133 - [GetX Flutter Firebase Auth Example](https://medium.com/@jeffmcmorris/getx-flutter-firebase-auth-example-b383c1dd1de2) - Article by Jeff McMorris. 1183 - [GetX Flutter Firebase Auth Example](https://medium.com/@jeffmcmorris/getx-flutter-firebase-auth-example-b383c1dd1de2) - Article by Jeff McMorris.
1134 - [Flutter State Management with GetX – Complete App](https://www.appwithflutter.com/flutter-state-management-with-getx/) - by App With Flutter. 1184 - [Flutter State Management with GetX – Complete App](https://www.appwithflutter.com/flutter-state-management-with-getx/) - by App With Flutter.
1135 - [Flutter Routing with Animation using Get Package](https://www.appwithflutter.com/flutter-routing-using-get-package/) - by App With Flutter. 1185 - [Flutter Routing with Animation using Get Package](https://www.appwithflutter.com/flutter-routing-using-get-package/) - by App With Flutter.
  1186 +- [A minimal example on dartpad](https://dartpad.dev/2b3d0d6f9d4e312c5fdbefc414c1727e?) - by [Roi Peker](https://github.com/roipeker)
@@ -48,14 +48,14 @@ @@ -48,14 +48,14 @@
48 [**Telegram (Portuguese)**](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g) 48 [**Telegram (Portuguese)**](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
49 49
50 # Wprowadzenie 50 # Wprowadzenie
51 -- GetX jest bardzo lekką i potężną biblioteką do Flattera. Łączy wysoką wydajność menadżera stanu, inteligętne dodawanie dependencies i zarządzanie routami w szybki i praktyczny sposób. 51 +- GetX jest bardzo lekką, a zarazem potężną biblioteką do Flattera. Łączy wysoką wydajność menadżera stanu, inteligętne dodawanie dependencies i zarządzanie routami w szybki i praktyczny sposób.
52 - GetX nie jest dla wszystkich, skupia się na jak najmniejszej konsumpcji zasobów (wydajności) ([zobacz benchmarki](https://github.com/jonataslaw/benchmarks)), używaniu łatwej skłani (produktywności) i daniu możliwości pełnego rozbicia View na z logiki biznesowej (organizacja). 52 - GetX nie jest dla wszystkich, skupia się na jak najmniejszej konsumpcji zasobów (wydajności) ([zobacz benchmarki](https://github.com/jonataslaw/benchmarks)), używaniu łatwej skłani (produktywności) i daniu możliwości pełnego rozbicia View na z logiki biznesowej (organizacja).
53 -- GetX która da Ci supermoce i zwiększy produktywność w tworzeniu projektu. Oszczędzi godziny zarówno początkującym jak i ekspoertom. 53 +- GetX da Ci supermoce i zwiększy produktywność w tworzeniu projektu. Oszczędzi godziny zarówno początkującym jak i ekspertom.
54 - Nawiguj bez podawania `context`, używaj open `dialogs`, `snackbarów` oraz `bottomsheetów` z każdego miejsca w kodzie. Zarządzaj stanami i dodawaj dependencies w prosty i praktyczny sposób! 54 - Nawiguj bez podawania `context`, używaj open `dialogs`, `snackbarów` oraz `bottomsheetów` z każdego miejsca w kodzie. Zarządzaj stanami i dodawaj dependencies w prosty i praktyczny sposób!
55 - Get jest bezpieczny, stabilny i aktualny. Oprócz tego oferuje szeroki zakres API, które nie są zawarte w standardowym frameworku. 55 - Get jest bezpieczny, stabilny i aktualny. Oprócz tego oferuje szeroki zakres API, które nie są zawarte w standardowym frameworku.
56 -- GetX nie jest przytłaczający. Ma wiele funkcjonalności pozwalajacych na rozpoczęcie programowania bez martwienia się o nic, ale wszystkie te funkcjonalności są w osobnych kontenerach będących dodane dopiero po ich użyciu. Jeśli tylko używasz menadżera stanu, tylko on będzie kompilowany. Jeśli używasz routów, lecz nic z menadżera stanu on nie będzie kompilowany. Możesz skompilować repozytorium benchmark i zobaczysz że używa tylko menadżera stanu. Aplikacje używajace Get są mniejsze niz inne ponieważ wszystkie rozwiązania GetX sa projektowane dla lekkości i wydajności. Jest to też zasługa Flutterowego AOT, które jest niesamowite i eliminuje nieużywane zasoby jak żaden inny framework. 56 +- GetX nie jest przytłaczający. Ma wiele funkcjonalności pozwalajacych na rozpoczęcie programowania bez martwienia się zupełnie nic. Wszystkie funkcjonalności są w osobnych kontenerach, które dodawane są dopiero po ich użyciu. Jeśli tylko używasz menadżera stanu, tylko on będzie kompilowany. Jeśli używasz routów, lecz nic z menadżera stanu to nie będzie on kompilowany. Możesz skompilować repozytorium benchmark i zobaczysz że używa tylko menadżera stanu. Aplikacje używajace Get są mniejsze niz inne, ponieważ wszystkie rozwiązania GetX są projektowane z myślą o lekkości i wydajności. Jest to też zasługa Flutterowego AOT, które jest niesamowite i eliminuje nieużywane zasoby jak żaden inny framework.
57 57
58 -**GetX zwiększa stwoja produktywność, lecz mozesz to jeszcze przyspieszyć instalując rozszerzenie [GetX extension](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets) do swojego VSCode**. Jeszcze nie dostępne w innych IDE. 58 +**GetX zwiększa twoja produktywność, lecz możesz to jeszcze przyspieszyć instalując rozszerzenie [GetX extension](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets) do swojego VSCode**. Jeszcze nie dostępne w innych IDE.
59 59
60 # Instalacja 60 # Instalacja
61 61
@@ -74,7 +74,7 @@ import 'package:get/get.dart'; @@ -74,7 +74,7 @@ import 'package:get/get.dart';
74 74
75 # Counter App z GetX 75 # Counter App z GetX
76 76
77 -Przykładowa aplikaja tworzona domyślnie podczas kreacji nowego projektu we Flaterze ma ponad 100 lini kodu (z komentarzami). By pokazać siłę Get pokarzę jak zrobić "licznik" ze zmienianą stan z każdym kliknięciem, zmianą stron i udostępniajac stan pomiędzy ekranami. Wszystko w zorganizowany sposób dzieląc buissnes logic z view w zaledwie 26 LINI KODU WŁĄCZAJĄC W TO KOMENTARZE. 77 +Przykładowa aplikaja tworzona domyślnie podczas kreacji nowego projektu we Flaterze ma ponad 100 lini kodu (z komentarzami). By pokazać siłę Get pokażę jak zrobić "licznik" ze zmianą stanu przy każdym kliknięciu, zmianą stron i udostępniajac stan pomiędzy ekranami. Wszystko w zorganizowany sposób dzieląc bussines logic z view w zaledwie 26 LINI KODU WŁĄCZAJĄC W TO KOMENTARZE.
78 78
79 -Krok 1: 79 -Krok 1:
80 Dodaj "Get" przed MaterialApp, zamieniając je na GetMaterialApp 80 Dodaj "Get" przed MaterialApp, zamieniając je na GetMaterialApp
@@ -84,10 +84,10 @@ Dodaj "Get" przed MaterialApp, zamieniając je na GetMaterialApp @@ -84,10 +84,10 @@ Dodaj "Get" przed MaterialApp, zamieniając je na GetMaterialApp
84 void main() => runApp(GetMaterialApp(home: Home())); 84 void main() => runApp(GetMaterialApp(home: Home()));
85 ``` 85 ```
86 86
87 -- Note: nie jest to modyfikaja MaterialApp, ponieważ GetMaterialApp nie jest zmodyfikowanym MaterialApp z Fluttera, jest tylko zkonfigurowanym Widgetem mającym domyślnie MaterialApp jako dziecko. Możesz to konfigurować ręcznie, ale nie jest to konieczne. GetMaterialApp jest niezbędne dla działania routów, snackbarów, bootomsheetów, internacjonalizacji, dialogów i wysokopoziomowych api powiązanych z routami i nieobecnościa kontekstu. Nie jest to jednak wymagane do używania zarzadzania stanem i dependencies. 87 +- Note: nie jest to modyfikaja MaterialApp, ponieważ GetMaterialApp nie jest zmodyfikowanym MaterialApp z Fluttera, jest tylko skonfigurowanym Widgetem mającym domyślnie MaterialApp jako dziecko. Możesz to konfigurować ręcznie, ale nie jest to konieczne. GetMaterialApp jest niezbędne dla działania routów, snackbarów, bootomsheetów, internacjonalizacji, dialogów i wysokopoziomowych api powiązanych z routami i nieobecnościa kontekstu. Nie jest to jednak wymagane do używania zarzadzania stanem i dependencies.
88 88
89 -Krok 2: 89 -Krok 2:
90 -Tworzymy klasę business logic i umieszczmy w niej wszystkie zmienne, metody oraz kontrolery. Możesz zmienić zmienna=ą na obserwowalną używajac prostego ".obs" 90 +Tworzymy klasę business logic i umieszczmy w niej wszystkie zmienne, metody oraz kontrolery. Możesz zmienić zmiennaą na obserwowalną używajac prostego subfixu ".obs"
91 91
92 ```dart 92 ```dart
93 class Controller extends GetxController{ 93 class Controller extends GetxController{
@@ -135,11 +135,11 @@ Wynik: @@ -135,11 +135,11 @@ Wynik:
135 135
136 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/counter-app-gif.gif) 136 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/counter-app-gif.gif)
137 137
138 -Jest to prosty projekt, ale już na jego przykładzie widać potęgę Get. Wzraz ze wzrostem rozmiaru aplikacji ta różnica tylko się powieksza. 138 +Jest to prosty projekt, ale już na jego przykładzie widać potęgę Get. Wraz ze wzrostem rozmiaru aplikacji ta różnica tylko się powiększa.
139 139
140 -Get był projektowany dla pracy z zespołem, ale równie dobrze sprawdza się w indywidualnej pracy. 140 +Get był projektowany dla pracy z zespołem, ale równie dobrze sprawdza się w indywidualnych projektach.
141 141
142 -Zawsze dotrzymuj deadlinów i dostarczaj swoje rozwiązania na czas bez straty na wydajności. Get nie jest dla wszystkich jak już wspominałem, ale jeśli identyfikujesz się z powyższym zdaniem Get jest dla ciebie. 142 +Zawsze dotrzymuj deadlinów i dostarczaj swoje rozwiązania na czas bez straty na wydajności. Get nie jest dla wszystkich jak już wspominałem, ale jeśli identyfikujesz się z powyższym zdaniem Get jest właśnie dla Ciebie.
143 143
144 # Trzy filary 144 # Trzy filary
145 145
@@ -151,15 +151,15 @@ Get nie jest ani lepszy, ani gorszy od innych menadżerów stanów, ale powinien @@ -151,15 +151,15 @@ Get nie jest ani lepszy, ani gorszy od innych menadżerów stanów, ale powinien
151 151
152 Definitywnie Get nie jest przeciwnikiem żadnego innego menadżera, ponieważ jest on mikroframeworkiem, nie tylko menadżerem stanu. Może być użyty samodzielnie, lub w koegzystencji. 152 Definitywnie Get nie jest przeciwnikiem żadnego innego menadżera, ponieważ jest on mikroframeworkiem, nie tylko menadżerem stanu. Może być użyty samodzielnie, lub w koegzystencji.
153 153
154 -Get ma bardzo lekki i prosty menadżer stanu (napisany w tylko 95 lini kodu), który nie używa ChangeNotifier. Sprosta on wymaganiom szczególnie nowych we Flutterze i nie sprawi problemu nawer w dużych aplikacjach. 154 +Get ma bardzo lekki i prosty menadżer stanu (napisany w tylko 95 lini kodu), który nie używa ChangeNotifier. Sprosta on wymaganiom szczególnie nowych we Flutterze i nie sprawi problemu nawet w dużych aplikacjach.
155 155
156 ### Reaktywny menadżer stanu 156 ### Reaktywny menadżer stanu
157 157
158 -Reaktywne programowanie możee dotrącać niektórych, ponieważ powszechnie jest uważane za skomplikowane. GetX zamienia to w coś prostego: 158 +Reaktywne programowanie może odtrącać niektórych, ponieważ powszechnie jest uważane za skomplikowane. GetX zamienia to w coś prostego:
159 159
160 -- Nie musisz tworzyć Strw=eamControllerów, 160 +- Nie musisz tworzyć StreamControllerów,
161 - Nie musisz tworzyć StreamBuildera dla każdej zmiennej, 161 - Nie musisz tworzyć StreamBuildera dla każdej zmiennej,
162 -- Nie ma potrzeby tworzenia klasy dla kżdego stanu, 162 +- Nie ma potrzeby tworzenia klasy dla każdego stanu,
163 - Nie musisz tworzyć Get dla inicjalnej zmiennej 163 - Nie musisz tworzyć Get dla inicjalnej zmiennej
164 164
165 Wyobraź sobie, że masz zmienną i za każdym razem jak zmienisz ją chcesz żeby wszystkie widżety używające jej automatycznie się zmieniły 165 Wyobraź sobie, że masz zmienną i za każdym razem jak zmienisz ją chcesz żeby wszystkie widżety używające jej automatycznie się zmieniły
@@ -183,11 +183,11 @@ Obx (() => Text (controller.name)); @@ -183,11 +183,11 @@ Obx (() => Text (controller.name));
183 To wszystko. *Proste*, co nie? 183 To wszystko. *Proste*, co nie?
184 184
185 ### Bardziej szczegółowo o menadżerze stanu 185 ### Bardziej szczegółowo o menadżerze stanu
186 -**Zobacz bardziej szczegółowe wytłumaczenie menadz=żera sranu [tutaj](./documentation/en_US/state_management.md). Znajdują się tam przykłady jak o różnice między prostym menadżerem stanu oraz reaktywnym** 186 +**Zobacz bardziej szczegółowe wytłumaczenie menadżera stanu [tutaj](./documentation/en_US/state_management.md). Znajdują się tam przykłady jak o różnice między prostym menadżerem stanu oraz reaktywnym**
187 187
188 ### Video tłumaczące użycie menadżera stanu 188 ### Video tłumaczące użycie menadżera stanu
189 189
190 -Amateur COder nagrał o tym niezwykły film: 190 +Tadas Petra nagrał o tym niezwykły film:
191 191
192 Link: [Complete GetX State Management](https://www.youtube.com/watch?v=CNpXbeI_slw) 192 Link: [Complete GetX State Management](https://www.youtube.com/watch?v=CNpXbeI_slw)
193 193
@@ -239,42 +239,42 @@ I użyj następujące np.: @@ -239,42 +239,42 @@ I użyj następujące np.:
239 ```dart 239 ```dart
240 if(data == 'sucess') madeAnything(); 240 if(data == 'sucess') madeAnything();
241 ``` 241 ```
242 -Zobacz, ze do żadnej z tych operacji nie potrzebowałeś contextu. Jest to jedna z głównych zalet GetX oszczędzającego na niepotrzebnej ogudowie z kod i dającego możliwość uzywania tych metod w klasie kontrolera. 242 +Zobacz, ze do żadnej z tych operacji nie potrzebowałeś contextu. Jest to jedna z głównych zalet GetX oszczędzającego na niepotrzebnej obudowie w kod i dającego możliwość używania tych metod w klasie kontrolera.
243 243
244 244
245 ### Więcej o routach 245 ### Więcej o routach
246 246
247 -**Get używa named routes i także oferuje niskopoziomową obsługę routów! Zobacz bardziej szczegółową dokumentacje [tutaj](./documentation/en_US/route_management.md)** 247 +**Get używa named routes oraz oferuje niskopoziomową obsługę routów! Zobacz bardziej szczegółową dokumentacje [tutaj](./documentation/en_US/route_management.md)**
248 248
249 ### Video tłumaczące użycie 249 ### Video tłumaczące użycie
250 250
251 -Amateur Coder nagrał o tym niezwykły film: 251 +Tadas Petra nagrał o tym niezwykły film:
252 252
253 Link: [Complete GetX Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI) 253 Link: [Complete GetX Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI)
254 254
255 ## Zarządzanie dependencies 255 ## Zarządzanie dependencies
256 256
257 -Get ma prosty i potężny menadżer dependencies. Pozwala on na otrzymanie tych samych klas jak twoje Bloc lub Kontroler piszac jedną linię kodu bez Provider context i inheritedWidget: 257 +Get ma prosty, a zarazem potężny menadżer dependencies. Pozwala on na otrzymanie tych samych klas jak twoje Bloc lub Kontroler pisząc jedną linię kodu bez Provider context i inheritedWidget:
258 258
259 ```dart 259 ```dart
260 Controller controller = Get.put(Controller()); // Rather Controller controller = Controller(); 260 Controller controller = Get.put(Controller()); // Rather Controller controller = Controller();
261 ``` 261 ```
262 262
263 -- Note: Jeśli używasz menadżera stanu Get zwróć uwafę na binding api, które pozwoli Ci łatwiej połączyć twój widok z kontrolerem. 263 +- Note: Jeśli używasz menadżera stanu Get zwróć uwagę na binding api, które pozwoli Ci łatwiej połączyć twój widok z kontrolerem.
264 https://github.com/jonataslaw/get 264 https://github.com/jonataslaw/get
265 -**Tip:** Menadżer dependency Get jest oddzielony od innych części pakietu więc jeśli już używasz menadzera stanu(którego kolwiek,bez różnicy) nie musisz przepisywać tego wszystkiego na nowo. Możesz używać tego dodawania dependencies bez poroblemu. 265 +**Tip:** Menadżer dependency Get jest oddzielony od innych części pakietu więc jeśli już używasz menadżera stanu(którego kolwiek, bez różnicy) nie musisz przepisywać tego wszystkiego na nowo. Możesz używać tego dodawania dependencies bez poroblemu.
266 266
267 ```dart 267 ```dart
268 controller.fetchApi(); 268 controller.fetchApi();
269 ``` 269 ```
270 -Wyobraź sobie, że musisz nawigować pomiędzy wieloma routami i potrzebujesz dane z kontrolerów z poprzednich ekranów. Musiałbyś użyć menadżera stanu z dodatkiem Providera albo Get_it, prawda? Otuż nie z Fet. Muszisz po prostu poprosić Get o znalezienie tego kontrolera i nie potrzebujesz przy tym dodatkowych dependencies. 270 +Wyobraź sobie, że musisz nawigować pomiędzy wieloma routami i potrzebujesz dane z kontrolerów z poprzednich ekranów. Musiałbyś użyć menadżera stanu z dodatkiem Providera albo Get_it, prawda? Otóż nie z Fet. Musisz po prostu poprosić Get o znalezienie tego kontrolera i nie potrzebujesz przy tym dodatkowych dependencies.
271 271
272 ```dart 272 ```dart
273 Controller controller = Get.find(); 273 Controller controller = Get.find();
274 -//Yes, it looks like Magic, Get will find your controller, and will deliver it to you. You can have 1 million controllersfeatury instantiated, Get will always give you the right controller. 274 +//Tak, to wygląda jak Magia, Get znjadzie Twój kontroler i Ci go dostarczy. Możesz mieć nawet MILION kontrolerów, a Get zawsze da Ci prawidłowy kontroler.
275 ``` 275 ```
276 276
277 -I wtedy będziesz mógł otrzymać bez problemu z niego dane 277 +I wtedy będziesz mógł otrzymać z niego dane bez żadnego problemu
278 278
279 ```dart 279 ```dart
280 Text(controller.textFromApi); 280 Text(controller.textFromApi);
@@ -287,8 +287,8 @@ Text(controller.textFromApi); @@ -287,8 +287,8 @@ Text(controller.textFromApi);
287 287
288 Możesz uczestniczyć w rozwoju projektu na różny sposób: 288 Możesz uczestniczyć w rozwoju projektu na różny sposób:
289 - Pomagając w tłumaczeniu readme na inne języki. 289 - Pomagając w tłumaczeniu readme na inne języki.
290 -- Dodając dokumentację do readme ( nawet nie połowa funkcji została jeszcze opisana).  
291 -- Pisząc artykuły i nagrywając filmy uczące użycia biblioteki Get (będą zamieszczone w readme, a w przyszłości na naszej Wiki). 290 +- Dodając dokumentację do readme (nawet połowa funkcji została jeszcze opisana).
  291 +- Pisząc artykuły i nagrywając filmy pokazujące użycie biblioteki Get (będą zamieszczone w readme, a w przyszłości na naszej Wiki).
292 - Oferując PR-y dla kodu i testów. 292 - Oferując PR-y dla kodu i testów.
293 - Dodając nowe funkcje. 293 - Dodając nowe funkcje.
294 294
@@ -298,7 +298,7 @@ Każda współpraca jest mile widziana! @@ -298,7 +298,7 @@ Każda współpraca jest mile widziana!
298 298
299 ## Zmiana motywu 299 ## Zmiana motywu
300 300
301 -Nie powinno się uzywać innego widżetu niż GetMaterialApp by go zaktualizować. To może powodować duplikacje kluczy. Wiele osób nawykło do prehistorycznego podejścia tworzenia widżetu "ThemeProvider" tylko po to by zmienić motyw aplikacji. Z Get nie jest to absolutnie wymagane. 301 +Nie powinno się używać innego widżetu niż GetMaterialApp by go zaktualizować. To może powodować duplikacje kluczy. Wiele osób nawykło do prehistorycznego podejścia tworzenia widżetu "ThemeProvider" tylko po to by zmienić motyw aplikacji. Z Get nie jest to wymagane.
302 302
303 Możesz stworzyć customowy motyw i łatwo go dodać z Get.changeTheme bez niepotrzebnego kodu. 303 Możesz stworzyć customowy motyw i łatwo go dodać z Get.changeTheme bez niepotrzebnego kodu.
304 304
@@ -314,7 +314,7 @@ Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());featury @@ -314,7 +314,7 @@ Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());featury
314 314
315 Kiedy ciemny motyw jest aktywny zmieni się on na jasny, w przeciwnym wypadku zmieni się na ciemny. 315 Kiedy ciemny motyw jest aktywny zmieni się on na jasny, w przeciwnym wypadku zmieni się na ciemny.
316 316
317 -Jeśli interesuje Cię jak zmieniać motywy podąrzaj za samouczkiem na Medium uczącym zmiany motywu z Get: 317 +Jeśli interesuje Cię jak zmieniać motywy podążaj za samouczkiem na Medium pokazującum zmianę motywu przy użyciu Get:
318 318
319 - [Dynamic Themes in 3 lines using Get](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Samouczek stworzony przez [Rod Brown](https://github.com/RodBr). 319 - [Dynamic Themes in 3 lines using Get](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Samouczek stworzony przez [Rod Brown](https://github.com/RodBr).
320 320
@@ -486,7 +486,7 @@ GetMaterialApp( @@ -486,7 +486,7 @@ GetMaterialApp(
486 ## Video tłumaczące inne funkcjonalności GetX 486 ## Video tłumaczące inne funkcjonalności GetX
487 487
488 488
489 -Amateur Coder nagrał niezwykły film tłumaczący powyższe zagadnienia! 489 +Tadas Petra nagrał niezwykły film tłumaczący powyższe zagadnienia!
490 490
491 Link: [GetX Other Features](https://youtu.be/ttQtlX_Q0eU) 491 Link: [GetX Other Features](https://youtu.be/ttQtlX_Q0eU)
492 492
@@ -504,7 +504,7 @@ Link: [GetX Other Features](https://youtu.be/ttQtlX_Q0eU) @@ -504,7 +504,7 @@ Link: [GetX Other Features](https://youtu.be/ttQtlX_Q0eU)
504 | NumX | `RxNum` | 504 | NumX | `RxNum` |
505 | DoubleX | `RxDouble` | 505 | DoubleX | `RxDouble` |
506 506
507 -RXController i GetBuilder teraz zostały połączone. Nie musisz już pamiętać którego kontrolerachcesz użyć, po prostu korzystaj z GetxController, będzie działać zarówno dla prostego jak i reaktywnego menadżera stanów. 507 +RXController i GetBuilder teraz zostały połączone. Nie musisz już pamiętać którego kontrolera chcesz użyć, po prostu korzystaj z GetxController, będzie działać zarówno dla prostego jak i reaktywnego menadżera stanów.
508 508
509 2- NamedRoutes 509 2- NamedRoutes
510 Wcześniej: 510 Wcześniej:
@@ -528,7 +528,7 @@ GetMaterialApp( @@ -528,7 +528,7 @@ GetMaterialApp(
528 ``` 528 ```
529 529
530 Po co ta zmiana? 530 Po co ta zmiana?
531 -Często może być niezbędnym decydowanie która strona będzie wyswietlana w zależności od parametru, lub tokenu logowania. Wczesniejsze podejscie było nieelastyczne nie pozwalając na to. Zawarcie strony w funkcji zmniejszyło sporzycie RAM-u, ze względu na niealokowanie routów od początku działania aplikacji. Pozwoliło to także na takie podejscie: 531 +Często może być niezbędnym decydowanie która strona będzie wyświetlana w zależności od parametru, lub tokenu logowania. Wczesniejsze podejście było nieelastyczne, ponieważ na to nie pozwalało. Zawarcie strony w funkcji zmniejszyło sporzycie RAM-u, ze względu na niealokowanie routów od początku działania aplikacji. Pozwoliło to także na takie podejscie:
532 532
533 ```dart 533 ```dart
534 534
@@ -81,9 +81,9 @@ It is possible to lazyLoad a dependency so that it will be instantiated only whe @@ -81,9 +81,9 @@ It is possible to lazyLoad a dependency so that it will be instantiated only whe
81 Get.lazyPut<ApiMock>(() => ApiMock()); 81 Get.lazyPut<ApiMock>(() => ApiMock());
82 82
83 Get.lazyPut<FirebaseAuth>( 83 Get.lazyPut<FirebaseAuth>(
84 - () => { 84 + () {
85 // ... some logic if needed 85 // ... some logic if needed
86 - return FirebaseAuth() 86 + return FirebaseAuth();
87 }, 87 },
88 tag: Math.random().toString(), 88 tag: Math.random().toString(),
89 fenix: true 89 fenix: true
@@ -309,7 +309,7 @@ getPages: [ @@ -309,7 +309,7 @@ getPages: [
309 GetPage( 309 GetPage(
310 name: '/', 310 name: '/',
311 page: () => HomeView(), 311 page: () => HomeView(),
312 - binding: BindingsBuilder(() => { 312 + binding: BindingsBuilder(() {
313 Get.lazyPut<ControllerX>(() => ControllerX()); 313 Get.lazyPut<ControllerX>(() => ControllerX());
314 Get.put<Service>(()=> Api()); 314 Get.put<Service>(()=> Api());
315 }), 315 }),
@@ -317,7 +317,7 @@ getPages: [ @@ -317,7 +317,7 @@ getPages: [
317 GetPage( 317 GetPage(
318 name: '/details', 318 name: '/details',
319 page: () => DetailsView(), 319 page: () => DetailsView(),
320 - binding: BindingsBuilder(() => { 320 + binding: BindingsBuilder(() {
321 Get.lazyPut<DetailsController>(() => DetailsController()); 321 Get.lazyPut<DetailsController>(() => DetailsController());
322 }), 322 }),
323 ), 323 ),
@@ -484,12 +484,12 @@ Get.bottomSheet( @@ -484,12 +484,12 @@ Get.bottomSheet(
484 ListTile( 484 ListTile(
485 leading: Icon(Icons.music_note), 485 leading: Icon(Icons.music_note),
486 title: Text('Music'), 486 title: Text('Music'),
487 - onTap: () => {} 487 + onTap: () {}
488 ), 488 ),
489 ListTile( 489 ListTile(
490 leading: Icon(Icons.videocam), 490 leading: Icon(Icons.videocam),
491 title: Text('Video'), 491 title: Text('Video'),
492 - onTap: () => {}, 492 + onTap: () {},
493 ), 493 ),
494 ], 494 ],
495 ), 495 ),
1 -- [State Management](#state-management)  
2 - - [Reactive State Manager](#reactive-state-manager) 1 +* [State Management](#state-management)
  2 + + [Reactive State Manager](#reactive-state-manager)
3 - [Advantages](#advantages) 3 - [Advantages](#advantages)
4 - [Maximum performance:](#maximum-performance) 4 - [Maximum performance:](#maximum-performance)
5 - [Declaring a reactive variable](#declaring-a-reactive-variable) 5 - [Declaring a reactive variable](#declaring-a-reactive-variable)
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 - [Why i have to use .value](#why-i-have-to-use-value) 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 - - [Simple State Manager](#simple-state-manager) 14 + + [Simple State Manager](#simple-state-manager)
15 - [Advantages](#advantages-1) 15 - [Advantages](#advantages-1)
16 - [Usage](#usage) 16 - [Usage](#usage)
17 - [How it handles controllers](#how-it-handles-controllers) 17 - [How it handles controllers](#how-it-handles-controllers)
@@ -19,30 +19,35 @@ @@ -19,30 +19,35 @@
19 - [Why it exists](#why-it-exists) 19 - [Why it exists](#why-it-exists)
20 - [Other ways of using it](#other-ways-of-using-it) 20 - [Other ways of using it](#other-ways-of-using-it)
21 - [Unique IDs](#unique-ids) 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) 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)
24 24
25 # State Management 25 # State Management
26 26
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. 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 -- _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. 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 With GetX everything is reactive, and nothing depends on code generators, increasing your productivity in all aspects of your development. 32 With GetX everything is reactive, and nothing depends on code generators, increasing your productivity in all aspects of your development.
32 -- _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.  
33 -- _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. 33 +
  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 +
34 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. 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.
35 -- _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. 38 +
  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 +
36 Most (if not all) current state managers will rebuild on the screen. 41 Most (if not all) current state managers will rebuild on the screen.
37 42
38 ## Reactive State Manager 43 ## Reactive State Manager
39 44
40 Reactive programming can alienate many people because it is said to be complicated. GetX turns reactive programming into something quite simple: 45 Reactive programming can alienate many people because it is said to be complicated. GetX turns reactive programming into something quite simple:
41 46
42 -- You won't need to create StreamControllers.  
43 -- You won't need to create a StreamBuilder for each variable  
44 -- You will not need to create a class for each state.  
45 -- You will not need to create a get for an initial value. 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.
46 51
47 Reactive programming with Get is as easy as using setState. 52 Reactive programming with Get is as easy as using setState.
48 53
@@ -50,13 +55,13 @@ Let's imagine that you have a name variable and want that every time you change @@ -50,13 +55,13 @@ Let's imagine that you have a name variable and want that every time you change
50 55
51 This is your count variable: 56 This is your count variable:
52 57
53 -```dart 58 +``` dart
54 var name = 'Jonatas Borges'; 59 var name = 'Jonatas Borges';
55 ``` 60 ```
56 61
57 To make it observable, you just need to add ".obs" to the end of it: 62 To make it observable, you just need to add ".obs" to the end of it:
58 63
59 -```dart 64 +``` dart
60 var name = 'Jonatas Borges'.obs; 65 var name = 'Jonatas Borges'.obs;
61 ``` 66 ```
62 67
@@ -64,34 +69,34 @@ That's all. It's *that* simple. @@ -64,34 +69,34 @@ That's all. It's *that* simple.
64 69
65 From now on, we might refer to this reactive-".obs"(ervables) variables as _Rx_. 70 From now on, we might refer to this reactive-".obs"(ervables) variables as _Rx_.
66 71
67 -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. 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.
68 73
69 This is the **magic of GetX**, thanks to Dart's capabilities. 74 This is the **magic of GetX**, thanks to Dart's capabilities.
70 75
71 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". 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".
72 77
73 -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? 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?
74 79
75 -No, you don't need a `StreamBuilder`, but you are right about static classes. 80 +No, you don't need a `StreamBuilder` , but you are right about static classes.
76 81
77 Well, in the view, we usually have a lot of boilerplate when we want to change a specific Widget, that's the Flutter way. 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.
78 With **GetX** you can also forget about this boilerplate code. 83 With **GetX** you can also forget about this boilerplate code.
79 84
80 -`StreamBuilder( … )`? `initialValue: …`? `builder: …`? Nope, you just need to place this variable inside an `Obx()` Widget. 85 +`StreamBuilder( … )` ? `initialValue: …` ? `builder: …` ? Nope, you just need to place this variable inside an `Obx()` Widget.
81 86
82 -```dart 87 +``` dart
83 Obx (() => Text (controller.name)); 88 Obx (() => Text (controller.name));
84 ``` 89 ```
85 90
86 -_What do you need to memorize?_ Only `Obx(() =>`. 91 +_What do you need to memorize?_ Only `Obx(() =>` .
87 92
88 You are just passing that Widget through an arrow-function into an `Obx()` (the "Observer" of the _Rx_). 93 You are just passing that Widget through an arrow-function into an `Obx()` (the "Observer" of the _Rx_).
89 94
90 `Obx` is pretty smart, and will only change if the value of `controller.name` changes. 95 `Obx` is pretty smart, and will only change if the value of `controller.name` changes.
91 96
92 -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 +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?**
93 98
94 -> 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` ?
95 100
96 It will just update when **any** of them changes. 101 It will just update when **any** of them changes.
97 102
@@ -102,28 +107,31 @@ Nope, just the **specific Widget** that uses that _Rx_ variable. @@ -102,28 +107,31 @@ Nope, just the **specific Widget** that uses that _Rx_ variable.
102 So, **GetX** only updates the screen, when the _Rx_ variable changes it's value. 107 So, **GetX** only updates the screen, when the _Rx_ variable changes it's value.
103 108
104 ``` 109 ```
  110 +
105 final isOpen = false.obs; 111 final isOpen = false.obs;
106 112
107 // NOTHING will happen... same value. 113 // NOTHING will happen... same value.
108 void onButtonTap() => isOpen.value=false; 114 void onButtonTap() => isOpen.value=false;
109 ``` 115 ```
  116 +
110 ### Advantages 117 ### Advantages
111 118
112 **GetX()** helps you when you need **granular** control over what's being updated. 119 **GetX()** helps you when you need **granular** control over what's being updated.
113 120
114 -If you do not need `unique IDs`, because all your variables will be modified when you perform an action, then use `GetBuilder`,  
115 -because it's a Simple State Updater (in blocks, like `setState()`), made in just a few lines of code. 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.
116 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 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.
117 124
118 If you need a **powerful** State Manager, you can't go wrong with **GetX**. 125 If you need a **powerful** State Manager, you can't go wrong with **GetX**.
119 126
120 It doesn't work with variables, but __flows__, everything in it are `Streams` under the hood. 127 It doesn't work with variables, but __flows__, everything in it are `Streams` under the hood.
  128 +
121 You can use _rxDart_ in conjunction with it, because everything are `Streams`, 129 You can use _rxDart_ in conjunction with it, because everything are `Streams`,
122 -you can listen the `event` of each "_Rx_ variable", 130 +you can listen to the `event` of each "_Rx_ variable",
123 because everything in it are `Streams`. 131 because everything in it are `Streams`.
124 132
125 It is literally a _BLoC_ approach, easier than _MobX_, and without code generators or decorations. 133 It is literally a _BLoC_ approach, easier than _MobX_, and without code generators or decorations.
126 -You can turn **anything** into an _"Observable"_ with just a `.obs`. 134 +You can turn **anything** into an _"Observable"_ with just a `.obs` .
127 135
128 ### Maximum performance: 136 ### Maximum performance:
129 137
@@ -134,19 +142,18 @@ If you experience any errors in your app, and send a duplicate change of State, @@ -134,19 +142,18 @@ If you experience any errors in your app, and send a duplicate change of State,
134 **GetX** will ensure it will not crash. 142 **GetX** will ensure it will not crash.
135 143
136 With **GetX** the State only changes if the `value` change. 144 With **GetX** the State only changes if the `value` change.
137 -That's the main difference between **GetX**, and using _`computed` from MobX_. 145 +That's the main difference between **GetX**, and using _ `computed` from MobX_.
138 When joining two __observables__, and one changes; the listener of that _observable_ will change as well. 146 When joining two __observables__, and one changes; the listener of that _observable_ will change as well.
139 147
140 -With **GetX**, if you join two variables, `GetX()` (similar to `Observer()`) will only rebuild if it implies a real change of State. 148 +With **GetX**, if you join two variables, `GetX()` (similar to `Observer()` ) will only rebuild if it implies a real change of State.
141 149
142 ### Declaring a reactive variable 150 ### Declaring a reactive variable
143 151
144 You have 3 ways to turn a variable into an "observable". 152 You have 3 ways to turn a variable into an "observable".
145 153
146 -  
147 1 - The first is using **`Rx{Type}`**. 154 1 - The first is using **`Rx{Type}`**.
148 155
149 -```dart 156 +``` dart
150 // initial value is recommended, but not mandatory 157 // initial value is recommended, but not mandatory
151 final name = RxString(''); 158 final name = RxString('');
152 final isLogged = RxBool(false); 159 final isLogged = RxBool(false);
@@ -158,7 +165,7 @@ final myMap = RxMap<String, int>({}); @@ -158,7 +165,7 @@ final myMap = RxMap<String, int>({});
158 165
159 2 - The second is to use **`Rx`** and use Darts Generics, `Rx<Type>` 166 2 - The second is to use **`Rx`** and use Darts Generics, `Rx<Type>`
160 167
161 -```dart 168 +``` dart
162 final name = Rx<String>(''); 169 final name = Rx<String>('');
163 final isLogged = Rx<Bool>(false); 170 final isLogged = Rx<Bool>(false);
164 final count = Rx<Int>(0); 171 final count = Rx<Int>(0);
@@ -171,9 +178,9 @@ final myMap = Rx<Map<String, int>>({}); @@ -171,9 +178,9 @@ final myMap = Rx<Map<String, int>>({});
171 final user = Rx<User>(); 178 final user = Rx<User>();
172 ``` 179 ```
173 180
174 -3 - The third, more practical, easier and preferred approach, just add **`.obs`** as a property of your `value`: 181 +3 - The third, more practical, easier and preferred approach, just add **`.obs`** as a property of your `value` :
175 182
176 -```dart 183 +``` dart
177 final name = ''.obs; 184 final name = ''.obs;
178 final isLogged = false.obs; 185 final isLogged = false.obs;
179 final count = 0.obs; 186 final count = 0.obs;
@@ -193,20 +200,19 @@ To be prepared, from now on, you should always start your _Rx_ variables with an @@ -193,20 +200,19 @@ To be prepared, from now on, you should always start your _Rx_ variables with an
193 200
194 > 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.
195 202
196 -You will literally add a "`.obs`" to the end of your variable, and **that’s it**, you’ve made it observable,  
197 -and its `.value`, well, will be the _initial value_).  
198 - 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_).
199 205
200 ### Using the values in the view 206 ### Using the values in the view
201 207
202 -```dart 208 +``` dart
203 // controller file 209 // controller file
204 final count1 = 0.obs; 210 final count1 = 0.obs;
205 final count2 = 0.obs; 211 final count2 = 0.obs;
206 int get sum => count1.value + count2.value; 212 int get sum => count1.value + count2.value;
207 ``` 213 ```
208 214
209 -```dart 215 +``` dart
210 // view file 216 // view file
211 GetX<Controller>( 217 GetX<Controller>(
212 builder: (controller) { 218 builder: (controller) {
@@ -228,30 +234,35 @@ GetX<Controller>( @@ -228,30 +234,35 @@ GetX<Controller>(
228 ), 234 ),
229 ``` 235 ```
230 236
231 -If we increment `count1.value++`, it will print:  
232 -- `count 1 rebuild`  
233 -- `count 3 rebuild` 237 +If we increment `count1.value++` , it will print:
  238 +
  239 +* `count 1 rebuild`
  240 +
  241 +* `count 3 rebuild`
234 242
235 -because `count1` has a value of `1`, and `1 + 0 = 1`, changing the `sum` getter value. 243 +because `count1` has a value of `1` , and `1 + 0 = 1` , changing the `sum` getter value.
236 244
237 -If we change `count2.value++`, it will print:  
238 -- `count 2 rebuild`  
239 -- `count 3 rebuild` 245 +If we change `count2.value++` , it will print:
240 246
241 -because `count2.value` changed, and the result of the `sum` is now `2`. 247 +* `count 2 rebuild`
  248 +
  249 +* `count 3 rebuild`
  250 +
  251 +because `count2.value` changed, and the result of the `sum` is now `2` .
  252 +
  253 +* NOTE: By default, the very first event will rebuild the widget, even if it is the same `value`.
242 254
243 -- NOTE: By default, the very first event will rebuild the widget, even if it is the same `value`.  
244 This behavior exists due to Boolean variables. 255 This behavior exists due to Boolean variables.
245 256
246 Imagine you did this: 257 Imagine you did this:
247 258
248 -```dart 259 +``` dart
249 var isLogged = false.obs; 260 var isLogged = false.obs;
250 ``` 261 ```
251 262
252 -And then, you checked if a user is "logged in" to trigger an event in `ever`. 263 +And then, you checked if a user is "logged in" to trigger an event in `ever` .
253 264
254 -```dart 265 +``` dart
255 @override 266 @override
256 onInit(){ 267 onInit(){
257 ever(isLogged, fireRoute); 268 ever(isLogged, fireRoute);
@@ -267,18 +278,18 @@ fireRoute(logged) { @@ -267,18 +278,18 @@ fireRoute(logged) {
267 } 278 }
268 ``` 279 ```
269 280
270 -if `hasToken` was `false`, there would be no change to `isLogged`, so `ever()` would never be called. 281 +if `hasToken` was `false` , there would be no change to `isLogged` , so `ever()` would never be called.
271 To avoid this type of behavior, the first change to an _observable_ will always trigger an event, 282 To avoid this type of behavior, the first change to an _observable_ will always trigger an event,
272 -even if it contains the same `.value`. 283 +even if it contains the same `.value` .
273 284
274 You can remove this behavior if you want, using: 285 You can remove this behavior if you want, using:
275 -`isLogged.firstRebuild = false;` 286 + `isLogged.firstRebuild = false;`
276 287
277 ### Conditions to rebuild 288 ### Conditions to rebuild
278 289
279 In addition, Get provides refined state control. You can condition an event (such as adding an object to a list), on a certain condition. 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.
280 291
281 -```dart 292 +``` dart
282 // First parameter: condition, must return true or false. 293 // First parameter: condition, must return true or false.
283 // Second parameter: the new value to apply if the condition is true. 294 // Second parameter: the new value to apply if the condition is true.
284 list.addIf(item < limit, item); 295 list.addIf(item < limit, item);
@@ -288,7 +299,7 @@ Without decorations, without a code generator, without complications :smile: @@ -288,7 +299,7 @@ Without decorations, without a code generator, without complications :smile:
288 299
289 Do you know Flutter's counter app? Your Controller class might look like this: 300 Do you know Flutter's counter app? Your Controller class might look like this:
290 301
291 -```dart 302 +``` dart
292 class CountController extends GetxController { 303 class CountController extends GetxController {
293 final count = 0.obs; 304 final count = 0.obs;
294 } 305 }
@@ -296,7 +307,7 @@ class CountController extends GetxController { @@ -296,7 +307,7 @@ class CountController extends GetxController {
296 307
297 With a simple: 308 With a simple:
298 309
299 -```dart 310 +``` dart
300 controller.count.value++ 311 controller.count.value++
301 ``` 312 ```
302 313
@@ -307,7 +318,8 @@ You could update the counter variable in your UI, regardless of where it is stor @@ -307,7 +318,8 @@ You could update the counter variable in your UI, regardless of where it is stor
307 You can transform anything on obs. Here are two ways of doing it: 318 You can transform anything on obs. Here are two ways of doing it:
308 319
309 * You can convert your class values to obs 320 * You can convert your class values to obs
310 -```dart 321 +
  322 +``` dart
311 class RxUser { 323 class RxUser {
312 final name = "Camila".obs; 324 final name = "Camila".obs;
313 final age = 18.obs; 325 final age = 18.obs;
@@ -315,7 +327,8 @@ class RxUser { @@ -315,7 +327,8 @@ class RxUser {
315 ``` 327 ```
316 328
317 * or you can convert the entire class to be an observable 329 * or you can convert the entire class to be an observable
318 -```dart 330 +
  331 +``` dart
319 class User { 332 class User {
320 User({String name, int age}); 333 User({String name, int age});
321 var name; 334 var name;
@@ -333,7 +346,7 @@ Lists are completely observable as are the objects within it. That way, if you a @@ -333,7 +346,7 @@ Lists are completely observable as are the objects within it. That way, if you a
333 You also don't need to use ".value" with lists, the amazing dart api allowed us to remove that. 346 You also don't need to use ".value" with lists, the amazing dart api allowed us to remove that.
334 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. 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.
335 348
336 -```dart 349 +``` dart
337 // On the controller 350 // On the controller
338 final String title = 'User Info:'.obs 351 final String title = 'User Info:'.obs
339 final list = List<User>().obs; 352 final list = List<User>().obs;
@@ -347,7 +360,7 @@ ListView.builder ( @@ -347,7 +360,7 @@ ListView.builder (
347 360
348 When you are making your own classes observable, there is a different way to update them: 361 When you are making your own classes observable, there is a different way to update them:
349 362
350 -```dart 363 +``` dart
351 // on the model file 364 // on the model file
352 // we are going to make the entire class observable instead of each attribute 365 // we are going to make the entire class observable instead of each attribute
353 class User() { 366 class User() {
@@ -356,7 +369,6 @@ class User() { @@ -356,7 +369,6 @@ class User() {
356 int age; 369 int age;
357 } 370 }
358 371
359 -  
360 // on the controller file 372 // on the controller file
361 final user = User().obs; 373 final user = User().obs;
362 // when you need to update the user variable: 374 // when you need to update the user variable:
@@ -385,7 +397,7 @@ You can literally add 3 letters to your pubspec (get) and a colon and start prog @@ -385,7 +397,7 @@ You can literally add 3 letters to your pubspec (get) and a colon and start prog
385 397
386 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. 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.
387 399
388 -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. 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.
389 401
390 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. 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.
391 403
@@ -400,7 +412,7 @@ Obviously, if you don't use a type, you will need to have an instance of your co @@ -400,7 +412,7 @@ Obviously, if you don't use a type, you will need to have an instance of your co
400 412
401 Workers will assist you, triggering specific callbacks when an event occurs. 413 Workers will assist you, triggering specific callbacks when an event occurs.
402 414
403 -```dart 415 +``` dart
404 /// Called every time `count1` changes. 416 /// Called every time `count1` changes.
405 ever(count1, (_) => print("$_ has been changed")); 417 ever(count1, (_) => print("$_ has been changed"));
406 418
@@ -413,28 +425,34 @@ debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1)); @@ -413,28 +425,34 @@ debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1));
413 /// Ignore all changes within 1 second. 425 /// Ignore all changes within 1 second.
414 interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1)); 426 interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
415 ``` 427 ```
416 -All workers (except `debounce`) have a `condition` named parameter, which can be a `bool` or a callback that returns a `bool`. 428 +
  429 +All workers (except `debounce` ) have a `condition` named parameter, which can be a `bool` or a callback that returns a `bool` .
417 This `condition` defines when the `callback` function executes. 430 This `condition` defines when the `callback` function executes.
418 431
419 All workers returns a `Worker` instance, that you can use to cancel ( via `dispose()` ) the worker. 432 All workers returns a `Worker` instance, that you can use to cancel ( via `dispose()` ) the worker.
420 433
421 -- **`ever`** 434 +
  435 +* **`ever`**
  436 +
422 is called every time the _Rx_ variable emits a new value. 437 is called every time the _Rx_ variable emits a new value.
423 438
424 -- **`everAll`**  
425 - Much like `ever`, but it takes a `List` of _Rx_ values Called every time its variable is changed. That's it. 439 +* **`everAll`**
  440 +
  441 + Much like `ever` , but it takes a `List` of _Rx_ values Called every time its variable is changed. That's it.
426 442
  443 +* **`once`**
427 444
428 -- **`once`**  
429 'once' is called only the first time the variable has been changed. 445 'once' is called only the first time the variable has been changed.
430 446
431 -- **`debounce`** 447 +* **`debounce`**
  448 +
432 '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. 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.
433 450
434 -- **`interval`** 451 +* **`interval`**
  452 +
435 '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. 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.
436 454
437 -- 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). 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).
438 456
439 ## Simple State Manager 457 ## Simple State Manager
440 458
@@ -466,7 +484,7 @@ That way, if you want an individual controller, you can assign IDs for that, or @@ -466,7 +484,7 @@ That way, if you want an individual controller, you can assign IDs for that, or
466 484
467 ### Usage 485 ### Usage
468 486
469 -```dart 487 +``` dart
470 // Create controller class and extends GetxController 488 // Create controller class and extends GetxController
471 class Controller extends GetxController { 489 class Controller extends GetxController {
472 int counter = 0; 490 int counter = 0;
@@ -487,13 +505,13 @@ GetBuilder<Controller>( @@ -487,13 +505,13 @@ GetBuilder<Controller>(
487 505
488 **Done!** 506 **Done!**
489 507
490 -- You have already learned how to manage states with Get. 508 +* You have already learned how to manage states with Get.
491 509
492 -- 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. 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.
493 511
494 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): 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):
495 513
496 -```dart 514 +``` dart
497 class OtherClass extends StatelessWidget { 515 class OtherClass extends StatelessWidget {
498 @override 516 @override
499 Widget build(BuildContext context) { 517 Widget build(BuildContext context) {
@@ -508,9 +526,9 @@ class OtherClass extends StatelessWidget { @@ -508,9 +526,9 @@ class OtherClass extends StatelessWidget {
508 526
509 ``` 527 ```
510 528
511 -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>()`) 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>()` )
512 530
513 -```dart 531 +``` dart
514 class Controller extends GetxController { 532 class Controller extends GetxController {
515 533
516 /// You do not need that. I recommend using it just for ease of syntax. 534 /// You do not need that. I recommend using it just for ease of syntax.
@@ -529,7 +547,7 @@ class Controller extends GetxController { @@ -529,7 +547,7 @@ class Controller extends GetxController {
529 547
530 And then you can access your controller directly, that way: 548 And then you can access your controller directly, that way:
531 549
532 -```dart 550 +``` dart
533 FloatingActionButton( 551 FloatingActionButton(
534 onPressed: () { 552 onPressed: () {
535 Controller.to.increment(), 553 Controller.to.increment(),
@@ -544,7 +562,7 @@ When you press FloatingActionButton, all widgets that are listening to the 'coun @@ -544,7 +562,7 @@ When you press FloatingActionButton, all widgets that are listening to the 'coun
544 562
545 Let's say we have this: 563 Let's say we have this:
546 564
547 -`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)`
548 566
549 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. 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.
550 568
@@ -557,7 +575,7 @@ Unless you need to use a mixin, like TickerProviderStateMixin, it will be totall @@ -557,7 +575,7 @@ Unless you need to use a mixin, like TickerProviderStateMixin, it will be totall
557 You can call all methods of a StatefulWidget directly from a GetBuilder. 575 You can call all methods of a StatefulWidget directly from a GetBuilder.
558 If you need to call initState() or dispose() method for example, you can call them directly; 576 If you need to call initState() or dispose() method for example, you can call them directly;
559 577
560 -```dart 578 +``` dart
561 GetBuilder<Controller>( 579 GetBuilder<Controller>(
562 initState: (_) => Controller.to.fetchApi(), 580 initState: (_) => Controller.to.fetchApi(),
563 dispose: (_) => Controller.to.closeStreams(), 581 dispose: (_) => Controller.to.closeStreams(),
@@ -567,7 +585,7 @@ GetBuilder<Controller>( @@ -567,7 +585,7 @@ GetBuilder<Controller>(
567 585
568 A much better approach than this is to use the onInit() and onClose() method directly from your controller. 586 A much better approach than this is to use the onInit() and onClose() method directly from your controller.
569 587
570 -```dart 588 +``` dart
571 @override 589 @override
572 void onInit() { 590 void onInit() {
573 fetchApi(); 591 fetchApi();
@@ -575,7 +593,7 @@ void onInit() { @@ -575,7 +593,7 @@ void onInit() {
575 } 593 }
576 ``` 594 ```
577 595
578 -- 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. 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.
579 597
580 ### Why it exists 598 ### Why it exists
581 599
@@ -587,7 +605,7 @@ You do not need to call the device, you have the onClose() method that will be c @@ -587,7 +605,7 @@ You do not need to call the device, you have the onClose() method that will be c
587 605
588 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: 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:
589 607
590 -```dart 608 +``` dart
591 class Controller extends GetxController { 609 class Controller extends GetxController {
592 StreamController<User> user = StreamController<User>(); 610 StreamController<User> user = StreamController<User>();
593 StreamController<String> name = StreamController<String>(); 611 StreamController<String> name = StreamController<String>();
@@ -604,15 +622,15 @@ class Controller extends GetxController { @@ -604,15 +622,15 @@ class Controller extends GetxController {
604 622
605 Controller life cycle: 623 Controller life cycle:
606 624
607 -- onInit() where it is created.  
608 -- onClose() where it is closed to make any changes in preparation for the delete method  
609 -- 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. 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.
610 628
611 ### Other ways of using it 629 ### Other ways of using it
612 630
613 You can use Controller instance directly on GetBuilder value: 631 You can use Controller instance directly on GetBuilder value:
614 632
615 -```dart 633 +``` dart
616 GetBuilder<Controller>( 634 GetBuilder<Controller>(
617 init: Controller(), 635 init: Controller(),
618 builder: (value) => Text( 636 builder: (value) => Text(
@@ -623,7 +641,7 @@ GetBuilder<Controller>( @@ -623,7 +641,7 @@ GetBuilder<Controller>(
623 641
624 You may also need an instance of your controller outside of your GetBuilder, and you can use these approaches to achieve this: 642 You may also need an instance of your controller outside of your GetBuilder, and you can use these approaches to achieve this:
625 643
626 -```dart 644 +``` dart
627 class Controller extends GetxController { 645 class Controller extends GetxController {
628 static Controller get to => Get.find(); 646 static Controller get to => Get.find();
629 [...] 647 [...]
@@ -639,7 +657,7 @@ GetBuilder<Controller>( @@ -639,7 +657,7 @@ GetBuilder<Controller>(
639 657
640 or 658 or
641 659
642 -```dart 660 +``` dart
643 class Controller extends GetxController { 661 class Controller extends GetxController {
644 // static Controller get to => Get.find(); // with no static get 662 // static Controller get to => Get.find(); // with no static get
645 [...] 663 [...]
@@ -653,9 +671,9 @@ GetBuilder<Controller>( @@ -653,9 +671,9 @@ GetBuilder<Controller>(
653 ), 671 ),
654 ``` 672 ```
655 673
656 -- 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: 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:
657 675
658 -```dart 676 +``` dart
659 Controller controller = Controller(); 677 Controller controller = Controller();
660 [...] 678 [...]
661 GetBuilder<Controller>( 679 GetBuilder<Controller>(
@@ -671,7 +689,7 @@ GetBuilder<Controller>( @@ -671,7 +689,7 @@ GetBuilder<Controller>(
671 689
672 If you want to refine a widget's update control with GetBuilder, you can assign them unique IDs: 690 If you want to refine a widget's update control with GetBuilder, you can assign them unique IDs:
673 691
674 -```dart 692 +``` dart
675 GetBuilder<Controller>( 693 GetBuilder<Controller>(
676 id: 'text' 694 id: 'text'
677 init: Controller(), // use it only first time on each controller 695 init: Controller(), // use it only first time on each controller
@@ -683,13 +701,13 @@ GetBuilder<Controller>( @@ -683,13 +701,13 @@ GetBuilder<Controller>(
683 701
684 And update it this form: 702 And update it this form:
685 703
686 -```dart 704 +``` dart
687 update(['text']); 705 update(['text']);
688 ``` 706 ```
689 707
690 You can also impose conditions for the update: 708 You can also impose conditions for the update:
691 709
692 -```dart 710 +``` dart
693 update(['text'], counter < 10); 711 update(['text'], counter < 10);
694 ``` 712 ```
695 713
@@ -701,6 +719,55 @@ Some people opened a feature request, as they wanted to use only one type of rea @@ -701,6 +719,55 @@ Some people opened a feature request, as they wanted to use only one type of rea
701 719
702 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. 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.
703 721
  722 +## StateMixin
  723 +
  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.
  727 +
  728 +``` dart
  729 +class Controller extends GetController with StateMixin<User>{}
  730 +```
  731 +
  732 +The `change()` method change the State whenever we want.
  733 +Just pass the data and the status in this way:
  734 +
  735 +```dart
  736 +change(data, status: RxStatus.success());
  737 +```
  738 +
  739 +RxStatus allow these status:
  740 +
  741 +``` dart
  742 +RxStatus.loading();
  743 +RxStatus.success();
  744 +RxStatus.empty();
  745 +RxStatus.error('message');
  746 +```
  747 +
  748 +To represent it in the UI, use:
  749 +
  750 +```dart
  751 +class OtherClass extends GetView<Controller> {
  752 + @override
  753 + Widget build(BuildContext context) {
  754 + return Scaffold(
  755 +
  756 + body: controller.obx(
  757 + (state)=>Text(state.name),
  758 +
  759 + // here you can put your custom loading indicator, but
  760 + // by default would be Center(child:CircularProgressIndicator())
  761 + onLoading: CustomLoadingIndicator(),
  762 + onEmpty: Text('No data found'),
  763 +
  764 + // here also you can set your own error widget, but by
  765 + // default will be an Center(child:Text(error))
  766 + onError: (error)=>Text(error),
  767 + ),
  768 + );
  769 +}
  770 +```
704 771
705 ## GetBuilder vs GetX vs Obx vs MixinBuilder 772 ## GetBuilder vs GetX vs Obx vs MixinBuilder
706 773
@@ -484,12 +484,12 @@ Get.bottomSheet( @@ -484,12 +484,12 @@ Get.bottomSheet(
484 ListTile( 484 ListTile(
485 leading: Icon(Icons.music_note), 485 leading: Icon(Icons.music_note),
486 title: Text('Music'), 486 title: Text('Music'),
487 - onTap: () => {} 487 + onTap: () {}
488 ), 488 ),
489 ListTile( 489 ListTile(
490 leading: Icon(Icons.videocam), 490 leading: Icon(Icons.videocam),
491 title: Text('Video'), 491 title: Text('Video'),
492 - onTap: () => {}, 492 + onTap: () {},
493 ), 493 ),
494 ], 494 ],
495 ), 495 ),
@@ -84,9 +84,9 @@ Anda bisa melakukan lazyload terhadap sebuah dependensi supaya dependensi terseb @@ -84,9 +84,9 @@ Anda bisa melakukan lazyload terhadap sebuah dependensi supaya dependensi terseb
84 Get.lazyPut<ApiMock>(() => ApiMock()); 84 Get.lazyPut<ApiMock>(() => ApiMock());
85 85
86 Get.lazyPut<FirebaseAuth>( 86 Get.lazyPut<FirebaseAuth>(
87 - () => { 87 + () {
88 // ... beberapa logic jika diperlukan.. 88 // ... beberapa logic jika diperlukan..
89 - return FirebaseAuth() 89 + return FirebaseAuth();
90 }, 90 },
91 tag: Math.random().toString(), 91 tag: Math.random().toString(),
92 fenix: true 92 fenix: true
@@ -322,7 +322,7 @@ getPages: [ @@ -322,7 +322,7 @@ getPages: [
322 GetPage( 322 GetPage(
323 name: '/', 323 name: '/',
324 page: () => HomeView(), 324 page: () => HomeView(),
325 - binding: BindingsBuilder(() => { 325 + binding: BindingsBuilder(() {
326 Get.lazyPut<ControllerX>(() => ControllerX()); 326 Get.lazyPut<ControllerX>(() => ControllerX());
327 Get.put<Service>(()=> Api()); 327 Get.put<Service>(()=> Api());
328 }), 328 }),
@@ -330,7 +330,7 @@ getPages: [ @@ -330,7 +330,7 @@ getPages: [
330 GetPage( 330 GetPage(
331 name: '/details', 331 name: '/details',
332 page: () => DetailsView(), 332 page: () => DetailsView(),
333 - binding: BindingsBuilder(() => { 333 + binding: BindingsBuilder(() {
334 Get.lazyPut<DetailsController>(() => DetailsController()); 334 Get.lazyPut<DetailsController>(() => DetailsController());
335 }), 335 }),
336 ), 336 ),
@@ -486,12 +486,12 @@ Get.bottomSheet( @@ -486,12 +486,12 @@ Get.bottomSheet(
486 ListTile( 486 ListTile(
487 leading: Icon(Icons.music_note), 487 leading: Icon(Icons.music_note),
488 title: Text('Music'), 488 title: Text('Music'),
489 - onTap: () => {} 489 + onTap: () {}
490 ), 490 ),
491 ListTile( 491 ListTile(
492 leading: Icon(Icons.videocam), 492 leading: Icon(Icons.videocam),
493 title: Text('Video'), 493 title: Text('Video'),
494 - onTap: () => {}, 494 + onTap: () {},
495 ), 495 ),
496 ], 496 ],
497 ), 497 ),
@@ -80,9 +80,9 @@ Get.put<S>( @@ -80,9 +80,9 @@ Get.put<S>(
80 Get.lazyPut<ApiMock>(() => ApiMock()); 80 Get.lazyPut<ApiMock>(() => ApiMock());
81 81
82 Get.lazyPut<FirebaseAuth>( 82 Get.lazyPut<FirebaseAuth>(
83 - () => { 83 + () {
84 // 어떤 로직이 필요하다면 ... 84 // 어떤 로직이 필요하다면 ...
85 - return FirebaseAuth() 85 + return FirebaseAuth();
86 }, 86 },
87 tag: Math.random().toString(), 87 tag: Math.random().toString(),
88 fenix: true 88 fenix: true
@@ -308,7 +308,7 @@ getPages: [ @@ -308,7 +308,7 @@ getPages: [
308 GetPage( 308 GetPage(
309 name: '/', 309 name: '/',
310 page: () => HomeView(), 310 page: () => HomeView(),
311 - binding: BindingsBuilder(() => { 311 + binding: BindingsBuilder(() {
312 Get.lazyPut<ControllerX>(() => ControllerX()); 312 Get.lazyPut<ControllerX>(() => ControllerX());
313 Get.put<Service>(()=> Api()); 313 Get.put<Service>(()=> Api());
314 }), 314 }),
@@ -316,7 +316,7 @@ getPages: [ @@ -316,7 +316,7 @@ getPages: [
316 GetPage( 316 GetPage(
317 name: '/details', 317 name: '/details',
318 page: () => DetailsView(), 318 page: () => DetailsView(),
319 - binding: BindingsBuilder(() => { 319 + binding: BindingsBuilder(() {
320 Get.lazyPut<DetailsController>(() => DetailsController()); 320 Get.lazyPut<DetailsController>(() => DetailsController());
321 }), 321 }),
322 ), 322 ),
@@ -484,12 +484,12 @@ Get.bottomSheet( @@ -484,12 +484,12 @@ Get.bottomSheet(
484 ListTile( 484 ListTile(
485 leading: Icon(Icons.music_note), 485 leading: Icon(Icons.music_note),
486 title: Text('Music'), 486 title: Text('Music'),
487 - onTap: () => {} 487 + onTap: () {}
488 ), 488 ),
489 ListTile( 489 ListTile(
490 leading: Icon(Icons.videocam), 490 leading: Icon(Icons.videocam),
491 title: Text('Video'), 491 title: Text('Video'),
492 - onTap: () => {}, 492 + onTap: () {},
493 ), 493 ),
494 ], 494 ],
495 ), 495 ),
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) 1 +- [상태 관리자](#상태-관리자)
  2 + - [반응형 상태 관리자](#반응형-상태-관리자)
  3 + - [장점](#장점)
  4 + - [최대의 성능](#최대의-성능)
  5 + - [반응형 변수 선언하기](#반응형-변수-선언하기)
  6 + - [반응형 상태를 갖는 간단한 방법](#반응형-상태를-갖는-간단한-방법)
  7 + - [변수를 화면에 적용하기](#변수를-화면에-적용하기)
  8 + - [재빌드에 조건 걸기](#재빌드에-조건-걸기)
  9 + - [.obs를 사용하는 방법](#obs를-사용하는-방법)
  10 + - [List를 사용할 때](#list를-사용할-때)
  11 + - [어째서 .value를 사용하는가](#어째서-value를-사용하는가)
12 - [Obx()](#obx) 12 - [Obx()](#obx)
13 - [Workers](#workers) 13 - [Workers](#workers)
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) 14 + - [간단한 상태 관리자](#간단한-상태-관리자)
  15 + - [장점](#장점-1)
  16 + - [사용법](#사용법)
  17 + - [controller의 동작 방식](#controller의-동작-방식)
  18 + - [StatefulWidget을 더 이상 사용할 필요없습니다](#statefulwidget을-더-이상-사용할-필요없습니다)
  19 + - [이 패키지의 목표](#이-패키지의-목표)
  20 + - [다른 사용법](#다른-사용법)
  21 + - [고유 ID](#고유-id)
  22 + - [2개의 상태 관리자 섞어쓰기](#2개의-상태-관리자-섞어쓰기)
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 -# State Management 25 +# 상태 관리자
26 26
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. 27 +GetX는 다른 상태 관리자처럼 Streams나 ChangeNotifier를 사용하지 않습니다. 어째서일까요? GetX를 사용하면 Android, iOS, 웹, Linux, macOS, Linux 용 어플리케이션뿐만 아니라, 서버 어플리케이션도 Flutter/GetX의 문법으로 만들 수 있습니다. 반응 시간을 줄이고, RAM을 효율적으로 사용하기 위해, 우리는 GetValue와 GetStream을 만들었습니다. GetValue와 GetStream은 적은 연산 자원으로 낮은 레이턴시와 높은 퍼포먼스를 보여줍니다. 우리는 이를 토대로 상태관리를 포함해 모든 리소스를 빌드합니다.
28 28
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 -With GetX everything is reactive, and nothing depends on code generators, increasing your productivity in all aspects of your development.  
32 -- _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.  
33 -- _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.  
34 -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.  
35 -- _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.  
36 -Most (if not all) current state managers will rebuild on the screen. 29 +- _복잡도_: 어떤 상태관리자들은 복잡하고 매우 비슷한 형태를 띕니다. GetX를 이용하면 모든 이벤트를 위한 클래스를 정의할 필요가 없습니다. 이는 당신의 코드를 매우 깔끔하게 만들어주며, 적을 코드들을 줄여줍니다. 많은 Flutter 개발자들이 이런 이유로 개발을 포기해왔지만, 드디어 상태관리를 해결해줄 엄청나게 간단한 방법이 나왔습니다.
  30 +- _code generators에 의존하지 않음_: 당신은 어플리케이션 개발을 위한 로직을 작성하는데 개발시간의 절반을 할애했을 것입니다. 어떤 상태관리자들은 code generator에 의존하여 읽기 쉬운 코드를 작성했을 것입니다. 변수를 바꾸고 build_runner를 실행해야 하는 것은 비생산적일 수 있으며, 심지어 Flutter가 이를 반영되기를 기다리면서 커피 한 잔을 즐겨야 할 정도로 오래 기다릴 수 있습니다. GetX는 모든것을 즉각적으로 반응합니다. code generator에 의존하지 않고, 모든 면에서 당신의 생산성을 높여줍니다.
  31 +- _필요없는 context_: 아마 당신은 비즈니스 로직을 UI에 반영하기 위해, 여러 위젯 컨트롤러에 context를 넘겨주었을 것입니다. context를 이용한 위젯을 사용하기 위해, context를 다양한 클래스와 함수들을 이용하여 전달하였을 것입니다. GetX를 이용하면 그럴 필요가 없습니다. context없이 controller만으로 접근하여 사용할 수 있습니다. 말 그대로 아무 의미 없이 context를 파라미터로 넘겨줄 필요가 없습니다.
  32 +- _세분화된 컨트롤_: 대부분의 상태관리자들은 ChangeNotifier을 기반으로 동작합니다. ChangeNotifier는 notifyListeners가 호출되면 모든 위젯들에게 알릴 것입니다. 만약 당신 스크린에 수많은 ChangeNotifier 클래스를 갖는 40개의 위젯이 있다면, 한 번 없데이트 할 때마다 모든 위젯들이 다시 빌드될 것입니다. GetX를 이용하면 위젯이 중첩되더라도, 변경된 위젯만 다시 빌드됩니다. 한 Obx가 ListView를 보고있고, 다른 Obx가 ListView 안의 checkbox를 보고있을 때, checkBox 값이 변경죄면, checkBox만 업데이트 되고, ListView 값이 변경되면 ListView만 업데이트 됩니다.
  33 +- _**정말** 바뀌었을 때만 재구성_: GetX는 흐름제어를 합니다. '진탁'이라는 Text를 화면에 보여준다고 해봅시다. 만약 당신이 obserable 변수인 '진탁'을 다시 한 번 '진탁'으로 변경한다면, 그 위젯은 재구성되지 않습니다. 왜냐하면 GetX는 '진탁'이 이미 Text로 보여주고 있다는 것을 알고 있기 때문에, 불필요한 재구성을 하지 않습니다. 대부분(모두일 수도 있는) 지금까지의 대부분의 상태관리자들은 스크린에 다시 빌드하여 보여줍니다.
37 34
38 -## Reactive State Manager 35 +## 반응형 상태 관리자
39 36
40 -Reactive programming can alienate many people because it is said to be complicated. GetX turns reactive programming into something quite simple: 37 +반응형 프로그래밍은 복잡하다고 말해지기 때문에 많은 사람들이 접하기 힘들게 합니다. GetX는 반응형 프로그래밍을 꽤 간단한 것으로 만들어줍니다:
41 38
42 -- You won't need to create StreamControllers.  
43 -- You won't need to create a StreamBuilder for each variable  
44 -- You will not need to create a class for each state.  
45 -- You will not need to create a get for an initial value. 39 +- StreamControllers를 생성할 필요가 없습니다.
  40 +- StreamBuilder를 각 변수마다 생성할 필요가 없습니다.
  41 +- 각 상태마다 클래스를 만들어줄 필요가 없습니다.
  42 +- 초기값을 위한 get을 만들어줄 필요가 없습니다.
46 43
47 -Reactive programming with Get is as easy as using setState. 44 +GetX와 함께하는 반응형 프로그래밍은 setState를 사용하는 것만큼 쉽습니다.
48 45
49 -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. 46 +이름 변수가 하나 있고, 이 변수가 변경될 때마다 해당 변수를 사용하는 모든 위젯들이 자동적으로 변경된다고 해봅시다.
50 47
51 -This is your count variable: 48 +여기 이름 변수가 있습니다.
52 49
53 ```dart 50 ```dart
54 var name = 'Jonatas Borges'; 51 var name = 'Jonatas Borges';
55 ``` 52 ```
56 53
57 -To make it observable, you just need to add ".obs" to the end of it: 54 +이 변수를 observable로 만들고 싶다면, 맨 뒤에 ".obs"만 붙이면 됩니다.
58 55
59 ```dart 56 ```dart
60 var name = 'Jonatas Borges'.obs; 57 var name = 'Jonatas Borges'.obs;
61 ``` 58 ```
62 59
63 -That's all. It's *that* simple. 60 +이게 끝입니다. 정말 쉽죠?
64 61
65 -From now on, we might refer to this reactive-".obs"(ervables) variables as _Rx_. 62 +지금부터, 우리는 이런 반응형-".obs"(ervables) 변수들을 _Rx_ 라고 부르겠습니다.
66 63
67 -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. 64 +우리가 내부에서 무엇을 했나요? 우리는 `String`의 `Stream`에 초기값인 `"Jonatas Borges"`를 할당했습니다. 우리는 `"Jonatas Borges"`을 사용하는 위젯들에게, 이제 이 변수에 "속한다"고 알리며 이 Rx 변수가 바뀔 때마다, 그 위젯들도 바뀌어야 한다고 알립니다.
68 65
69 -This is the **magic of GetX**, thanks to Dart's capabilities. 66 +이것이 Dart 언어의 기능에 기반한, **GetX의 마법**입니다.
70 67
71 -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". 68 +하지만, 알다시피 static 클래스들은 "자동 변경"할 힘이 없기 때문에, `위젯`은 함수 안에 있는 경우에만 변경이 가능합니다.
72 69
73 -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? 70 +몇몇 변수를 동일한 범위 내에서 변화시키고 싶을 때, 당신은 `StreamBuilder`를 생성하여 이 변수를 지켜보면서 변화를 감지하고, "연쇄적으로" 중첩된 `StreamBuilder`를 만들 것입니다, 맞죠?
74 71
75 -No, you don't need a `StreamBuilder`, but you are right about static classes. 72 +아뇨, 더 이상 `StreamBuilder`를 만들 필요 없습니다. 하지만 static 클래스를 사용한다는 점은 맞아요.
76 73
77 -Well, in the view, we usually have a lot of boilerplate when we want to change a specific Widget, that's the Flutter way.  
78 -With **GetX** you can also forget about this boilerplate code. 74 +특정한 위젯을 변경하고 싶을 때, 우리는 모양이 비슷한 코드들을 봐야 했습니다. 그건 Flutter 방식이죠. **GetX**를 이용하면 이런 비슷한 모양의 코드는 잊어버릴 수 있습니다.
79 75
80 -`StreamBuilder( … )`? `initialValue: …`? `builder: …`? Nope, you just need to place this variable inside an `Obx()` Widget. 76 +`StreamBuilder( … )`? `initialValue: …`? `builder: …`? 아뇨, 당신은 그저 `Obx()` 위젯 안에 변수를 넣기만 하면 됩니다.
81 77
82 ```dart 78 ```dart
83 Obx (() => Text (controller.name)); 79 Obx (() => Text (controller.name));
84 ``` 80 ```
85 81
86 -_What do you need to memorize?_ Only `Obx(() =>`. 82 +_당신이 기억해야할 것은?_ `Obx(() =>`만 기억하세요.
87 83
88 -You are just passing that Widget through an arrow-function into an `Obx()` (the "Observer" of the _Rx_). 84 +당신은 화살표함수를 통해 그 위젯을 `Obx()`으로 전달하는 것입니다. (그 _Rx_ 의 "Observer")
89 85
90 -`Obx` is pretty smart, and will only change if the value of `controller.name` changes. 86 +`Obx`는 꽤 스마트하며 `controller.name`이 바뀔 경우에만 바뀔 것입니다.
91 87
92 -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?** 88 +만약 `name`이 `"John"`이고, 당신이 이를 `"John"` (`name.value = "John"`)으로 바꾼다면, 기존 `value`와 동일하므로 화면상으로 바뀌는 것이 없습니다. 그리고 `Obx`는 리소스를 아끼기 위해 새 값을 무시하고 재빌드하지 않습니다. **놀랍지 않나요?**
93 89
94 -> So, what if I have 5 _Rx_ (observable) variables within an `Obx`? 90 +> 그래서, 제가 만약 5개의 _Rx_ (observable) 변수를 `Obx`안에 가지고 있다면 아떻게 되나요?
95 91
96 -It will just update when **any** of them changes. 92 +그 변수들 중 **아무거나** 변경이 되었을 때 업데이트 됩니다.
97 93
98 -> And if I have 30 variables in a class, when I update one, will it update **all** the variables that are in that class? 94 +> 그리고 제가 만약 클래스 안에 30개의 변수를 갖고 있고 하나만 업데이트 했다면, 클래스 안의 **모든** 변수가 업데이트 되나요?
99 95
100 -Nope, just the **specific Widget** that uses that _Rx_ variable. 96 +아뇨, 단지 그 _Rx_ 변수를 사용하는 **특정한 위젯만** 업데이트 됩니다.
101 97
102 -So, **GetX** only updates the screen, when the _Rx_ variable changes it's value. 98 +그래서 **GetX**는 _Rx_ 변수의 변경이 있을 때만 화면에 업데이트 합니다.
103 99
104 ``` 100 ```
105 final isOpen = false.obs; 101 final isOpen = false.obs;
106 102
107 -// NOTHING will happen... same value. 103 +// 아무일도 일어나지 않습니다. 동일한 값이기 때문입니다.
108 void onButtonTap() => isOpen.value=false; 104 void onButtonTap() => isOpen.value=false;
109 ``` 105 ```
110 -### Advantages 106 +### 장점
111 107
112 -**GetX()** helps you when you need **granular** control over what's being updated. 108 +**GetX()** 는 업데이트된 것들을 **세부적으로** 제어해야할 때 유용합니다.
113 109
114 -If you do not need `unique IDs`, because all your variables will be modified when you perform an action, then use `GetBuilder`,  
115 -because it's a Simple State Updater (in blocks, like `setState()`), made in just a few lines of code.  
116 -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. 110 +어떤 동작을 수행할 때 모든 변수가 수정되어 `고유 ID`가 필요없을 때 `GetBuilder`를 사용하세요. `GetBuilder`는 단 몇줄의 코드로 상태를 변경시켜줍니다(`setState()`처럼). 이것은 단순하면서 CPU에 최소한의 부담을 주며, State 재빌드라는 하나의 목적을 수행하기 위해 가능한한 최소의 리소스를 사용합니다.
117 111
118 -If you need a **powerful** State Manager, you can't go wrong with **GetX**. 112 +**강력한** 상택 관리자가 필요하다면, **GetX**와 함께하세요.
119 113
120 -It doesn't work with variables, but __flows__, everything in it are `Streams` under the hood.  
121 -You can use _rxDart_ in conjunction with it, because everything are `Streams`,  
122 -you can listen the `event` of each "_Rx_ variable",  
123 -because everything in it are `Streams`. 114 +GetX는 변수를 이용하지 않고, 내부에서 모든 것이 `Streams`로 구성된 __flow__ 를 이용합니다.
  115 +모든 것이 `Streams`이기 때문에, 접속사로써 _rxDart_ 를 이용합니다.
  116 +모든 것이 `Streams`이기 때문에, 각 "_Rx_ 변수"의 `event`를 주시할 수 있습니다.
124 117
125 -It is literally a _BLoC_ approach, easier than _MobX_, and without code generators or decorations.  
126 -You can turn **anything** into an _"Observable"_ with just a `.obs`. 118 +말 그대로 _BLoC_ 의 접근 법이며, generator와 decoration 없이 _MobX_ 보다 쉽습니다.
  119 +**모든 것들을** `.obs`를 붙임으로써 _"Observable"_ 하게 만들 수 있습니다.
127 120
128 -### Maximum performance: 121 +### 최대의 성능
129 122
130 -In addition to having a smart algorithm for minimal rebuilds, **GetX** uses comparators  
131 -to make sure the State has changed. 123 +최소의 재빌드를 위해 똑똑한 알고리즘을 적용하기 위해, **GetX**는 상태가 변했는지 확인하는 comparator를 사용합니다.
132 124
133 -If you experience any errors in your app, and send a duplicate change of State,  
134 -**GetX** will ensure it will not crash. 125 +당신의 앱에서 에러가 발생하고 상태 변경을 중복하여 보내면, **GetX**는 충돌하지 않도록 보장해줍니다.
135 126
136 -With **GetX** the State only changes if the `value` change.  
137 -That's the main difference between **GetX**, and using _`computed` from MobX_.  
138 -When joining two __observables__, and one changes; the listener of that _observable_ will change as well. 127 +**GetX**를 사용하면 `value`가 변경된 경우만 상태가 변경됩니다.
  128 +이 점이 **GetX**와 _`computed`를 사용하는 MobX_ 와의 주요 차이점입니다.
  129 +2개의 __observable__ 변수를 결합하고 하나만 변경되는 경우, 그 _observable_ 를 참조하는 것 또한 변경됩니다.
139 130
140 -With **GetX**, if you join two variables, `GetX()` (similar to `Observer()`) will only rebuild if it implies a real change of State. 131 +**GetX**를 사용하면, 2개의 변수를 결합한 경우 (`Oberver()`와 비슷한)`GetX()`는 정말 상태가 변경된 경우만 재빌드됩니다.
141 132
142 -### Declaring a reactive variable 133 +### 반응형 변수 선언하기
143 134
144 -You have 3 ways to turn a variable into an "observable". 135 +변수를 "observable"하게 만드는 방법은 3가지가 있습니다.
145 136
146 137
147 -1 - The first is using **`Rx{Type}`**. 138 +1 - 첫 번째 방법: **`Rx{Type}`**.
148 139
149 ```dart 140 ```dart
150 -// initial value is recommended, but not mandatory 141 +// 초기값을 설정하는 것을 추천하지만, 필수는 아닙니다.
151 final name = RxString(''); 142 final name = RxString('');
152 final isLogged = RxBool(false); 143 final isLogged = RxBool(false);
153 final count = RxInt(0); 144 final count = RxInt(0);
@@ -156,23 +147,25 @@ final items = RxList<String>([]); @@ -156,23 +147,25 @@ final items = RxList<String>([]);
156 final myMap = RxMap<String, int>({}); 147 final myMap = RxMap<String, int>({});
157 ``` 148 ```
158 149
159 -2 - The second is to use **`Rx`** and use Darts Generics, `Rx<Type>` 150 +2 - 두 번째 방법: **`Rx`**와 Dart의 제너릭을 이용 `Rx<Type>`
160 151
161 ```dart 152 ```dart
162 final name = Rx<String>(''); 153 final name = Rx<String>('');
163 final isLogged = Rx<Bool>(false); 154 final isLogged = Rx<Bool>(false);
164 final count = Rx<Int>(0); 155 final count = Rx<Int>(0);
165 final balance = Rx<Double>(0.0); 156 final balance = Rx<Double>(0.0);
166 -final number = Rx<Num>(0) 157 +final number = Rx<Num>(0);
167 final items = Rx<List<String>>([]); 158 final items = Rx<List<String>>([]);
168 final myMap = Rx<Map<String, int>>({}); 159 final myMap = Rx<Map<String, int>>({});
169 160
170 -// Custom classes - it can be any class, literally 161 +// 커스텀 클래스 - 그 어떤 클래스도 가능합니다
171 final user = Rx<User>(); 162 final user = Rx<User>();
172 ``` 163 ```
173 164
174 3 - The third, more practical, easier and preferred approach, just add **`.obs`** as a property of your `value`: 165 3 - The third, more practical, easier and preferred approach, just add **`.obs`** as a property of your `value`:
175 166
  167 +3 - 세 번째 방법: 실용적이며 쉽고 선호되는 방법으로, 단순히 **`.obs`**`value`의 속성으로 덧붙이는 방법
  168 +
176 ```dart 169 ```dart
177 final name = ''.obs; 170 final name = ''.obs;
178 final isLogged = false.obs; 171 final isLogged = false.obs;
@@ -182,22 +175,22 @@ final number = 0.obs; @@ -182,22 +175,22 @@ final number = 0.obs;
182 final items = <String>[].obs; 175 final items = <String>[].obs;
183 final myMap = <String, int>{}.obs; 176 final myMap = <String, int>{}.obs;
184 177
185 -// Custom classes - it can be any class, literally 178 +// 커스텀 클래스 - 그 어떤 클래스도 가능합니다
186 final user = User().obs; 179 final user = User().obs;
187 ``` 180 ```
188 181
189 -##### Having a reactive state, is easy. 182 +##### 반응형 상태를 갖는 간단한 방법
190 183
191 -As we know, _Dart_ is now heading towards _null safety_.  
192 -To be prepared, from now on, you should always start your _Rx_ variables with an **initial value**. 184 +알다시피 _Dart_ 는 _null safety_ 가 곧 도입될 것입니다.
  185 +이를 대비하기 위해 지금부터, _Rx_ 변수를 항상 **초기값**으로 초기화해주세요.
193 186
194 -> Transforming a variable into an _observable_ + _initial value_ with **GetX** is the simplest, and most practical approach. 187 +> 변수를 **GetX** 를 이용하여 _observable_ + _초기값_ 으로 바꾸는 것은 매우 쉽고 실용적입니다.
195 188
196 -You will literally add a "`.obs`" to the end of your variable, and **that’s it**, you’ve made it observable,  
197 -and its `.value`, well, will be the _initial value_). 189 +변수의 맨 뒤에 "`.obs`" 글자를 붙이기만 하면 되고, **이게 다입니다**.
  190 +당신은 변수를 observable 하게 만들었으며 `.value`를 이용하여 _초기값_ 에 접근할 수 있습니다.
198 191
199 192
200 -### Using the values in the view 193 +### 변수를 화면에 적용하기
201 194
202 ```dart 195 ```dart
203 // controller file 196 // controller file
@@ -222,34 +215,36 @@ GetX<Controller>( @@ -222,34 +215,36 @@ GetX<Controller>(
222 ), 215 ),
223 GetX<Controller>( 216 GetX<Controller>(
224 builder: (controller) { 217 builder: (controller) {
225 - print("count 3 rebuild"); 218 + print("sum rebuild");
226 return Text('${controller.sum}'); 219 return Text('${controller.sum}');
227 }, 220 },
228 ), 221 ),
229 ``` 222 ```
230 223
231 -If we increment `count1.value++`, it will print: 224 +`count1.value++`를 하면, 다음이 출력됩니다:
232 - `count 1 rebuild` 225 - `count 1 rebuild`
233 -- `count 3 rebuild` 226 +- `sum rebuild`
234 227
235 because `count1` has a value of `1`, and `1 + 0 = 1`, changing the `sum` getter value. 228 because `count1` has a value of `1`, and `1 + 0 = 1`, changing the `sum` getter value.
236 229
237 -If we change `count2.value++`, it will print: 230 +왜냐하면 `count1`은 `1`을 갖고 있고, `1 + 0 = 1`이며 `sum` getter의 값을 변경하기 때문입니다.
  231 +
  232 +`count2.value++`를 하면, 다음이 출력됩니다:
238 - `count 2 rebuild` 233 - `count 2 rebuild`
239 -- `count 3 rebuild` 234 +- `sum rebuild`
  235 +
  236 +왜냐하면 `count2.value`가 바뀌었고 `sum` 결과는 이제 `2`이기 때문입니다.
240 237
241 -because `count2.value` changed, and the result of the `sum` is now `2`.  
242 238
243 -- NOTE: By default, the very first event will rebuild the widget, even if it is the same `value`.  
244 - This behavior exists due to Boolean variables. 239 +- 참고: 기본적으로, 동일한 `value`로 변경되더라도, 첫 번째 이벤트는 위젯을 재빌드합니다. 이 동작은 Boolean 변수로 인해 일어납니다.
245 240
246 -Imagine you did this: 241 +다음과 같이 했다고 생각해봅시다:
247 242
248 ```dart 243 ```dart
249 var isLogged = false.obs; 244 var isLogged = false.obs;
250 ``` 245 ```
251 246
252 -And then, you checked if a user is "logged in" to trigger an event in `ever`. 247 +그리고 `ever`에서 이벤트를 발생시키기 위해, 사용자가 "로그인" 되어있는지 확인한다고 해봅시다.
253 248
254 ```dart 249 ```dart
255 @override 250 @override
@@ -267,26 +262,26 @@ fireRoute(logged) { @@ -267,26 +262,26 @@ fireRoute(logged) {
267 } 262 }
268 ``` 263 ```
269 264
270 -if `hasToken` was `false`, there would be no change to `isLogged`, so `ever()` would never be called.  
271 -To avoid this type of behavior, the first change to an _observable_ will always trigger an event,  
272 -even if it contains the same `.value`. 265 +만약 `hasToken`이 `false`라면, `isLogged`에 변화는 없을 것입니다. 그러면 `ever()`는 호출되지 않을 것입니다.
  266 +이런 동작을 피하기 위해서, `.value`가 동일한 값으로 변경되더라도 _observable_ 의 첫 변경은 이벤트를 발생시킬 것입니다.
273 267
274 -You can remove this behavior if you want, using: 268 +이런 동작을 원하지 않는다면, 다음으로 막을 수 있습니다:
275 `isLogged.firstRebuild = false;` 269 `isLogged.firstRebuild = false;`
276 270
277 -### Conditions to rebuild  
278 271
279 -In addition, Get provides refined state control. You can condition an event (such as adding an object to a list), on a certain condition. 272 +### 재빌드에 조건 걸기
  273 +
  274 +또한, Get은 정교한 상태 관리 기능을 제공합니다. 특정 조건에서 이벤트를 조건화할 수 있습니다.(리스트에 요소를 추가하는 등)
280 275
281 ```dart 276 ```dart
282 -// First parameter: condition, must return true of false  
283 -// Second parameter: the new value to aplly if the condition is true 277 +// 첫 번째 parameter: 조건, 반드시 true 혹은 false를 return
  278 +// 두 번째 parameter: 조건이 true 일 경우 적용할 새 value
284 list.addIf(item < limit, item); 279 list.addIf(item < limit, item);
285 ``` 280 ```
286 281
287 -Without decorations, without a code generator, without complications :smile: 282 +decoration 없이, code generator 없이, 복잡함 없이 :smile:
288 283
289 -Do you know Flutter's counter app? Your Controller class might look like this: 284 +Flutter의 counter 앱을 아시나요? 당신의 Controller 클래스는 아마 다음과 같을 것입니다.
290 285
291 ```dart 286 ```dart
292 class CountController extends GetxController { 287 class CountController extends GetxController {
@@ -294,19 +289,19 @@ class CountController extends GetxController { @@ -294,19 +289,19 @@ class CountController extends GetxController {
294 } 289 }
295 ``` 290 ```
296 291
297 -With a simple: 292 +간단합니다:
298 293
299 ```dart 294 ```dart
300 controller.count.value++ 295 controller.count.value++
301 ``` 296 ```
302 297
303 -You could update the counter variable in your UI, regardless of where it is stored. 298 +어디에서 변경되든지 간에 관계없이, counter 변수를 당신의 UI 내에서 업데이트 할 수 있습니다.
304 299
305 -### Where .obs can be used 300 +### .obs를 사용하는 방법
306 301
307 -You can transform anything on obs. Here are two ways of doing it: 302 +그 어떠한 것도 obs로 바꿀 수 있습니다. 2가지 방법이 있습니다.
308 303
309 -* You can convert your class values to obs 304 +* 클래스 값들을 obs로 바꿀 수 있습니다.
310 ```dart 305 ```dart
311 class RxUser { 306 class RxUser {
312 final name = "Camila".obs; 307 final name = "Camila".obs;
@@ -314,7 +309,7 @@ class RxUser { @@ -314,7 +309,7 @@ class RxUser {
314 } 309 }
315 ``` 310 ```
316 311
317 -* or you can convert the entire class to be an observable 312 +* 또는 클래스 전체를 observable로 만들 수 있습니다.
318 ```dart 313 ```dart
319 class User { 314 class User {
320 User({String name, int age}); 315 User({String name, int age});
@@ -322,16 +317,16 @@ class User { @@ -322,16 +317,16 @@ class User {
322 var age; 317 var age;
323 } 318 }
324 319
325 -// when instantianting: 320 +// 인스턴스화 할때
326 final user = User(name: "Camila", age: 18).obs; 321 final user = User(name: "Camila", age: 18).obs;
327 ``` 322 ```
328 323
329 -### Note about Lists 324 +### List를 사용할 때
330 325
331 -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. 326 +리스트내 요소들과 마찬가지로 리스트 또한 완벽하게 observable로 만들 수 있습니다. 이렇게 하면, 리스트에 요소를 추가하였을 때 자동적으로 그 리스트를 사용하는 위젯들을 리빌드할 수 있습니다.
332 327
333 -You also don't need to use ".value" with lists, the amazing dart api allowed us to remove that.  
334 -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. 328 +리스트는 ".value"를 이용할 필요가 없습니다. 놀랍게도 dart api가 ".value" 없이도 사용할 수 있게 만들어줍니다.
  329 +불행히도 String, int와 같은 primitive type들은 확장할 수 없기때문에 ".value"가 반드시 필요합니다만, getter와 setter를 이용하면 이러한 문제는 해결됩니다.
335 330
336 ```dart 331 ```dart
337 // On the controller 332 // On the controller
@@ -339,17 +334,17 @@ final String title = 'User Info:'.obs @@ -339,17 +334,17 @@ final String title = 'User Info:'.obs
339 final list = List<User>().obs; 334 final list = List<User>().obs;
340 335
341 // on the view 336 // on the view
342 -Text(controller.title.value), // String need to have .value in front of it 337 +Text(controller.title.value), // String은 .value가 필요합니다
343 ListView.builder ( 338 ListView.builder (
344 - itemCount: controller.list.length // lists don't need it 339 + itemCount: controller.list.length // 리스트는 .value가 필요없습니다.
345 ) 340 )
346 ``` 341 ```
347 342
348 -When you are making your own classes observable, there is a different way to update them: 343 +당신이 만든 observable 클래스를 만들었을 때, 업데이트를 하는 다른 방법이 있습니다.
349 344
350 ```dart 345 ```dart
351 -// on the model file  
352 -// we are going to make the entire class observable instead of each attribute 346 +// model 파일에서
  347 +// 각 field들을 observable로 만드는 대신, 클래스 전체를 observable로 만들 것입니다.
353 class User() { 348 class User() {
354 User({this.name = '', this.age = 0}); 349 User({this.name = '', this.age = 0});
355 String name; 350 String name;
@@ -357,141 +352,146 @@ class User() { @@ -357,141 +352,146 @@ class User() {
357 } 352 }
358 353
359 354
360 -// on the controller file 355 +// controller 파일에서
361 final user = User().obs; 356 final user = User().obs;
362 // when you need to update the user variable: 357 // when you need to update the user variable:
363 -user.update( (user) { // this parameter is the class itself that you want to update 358 +// user의 변수를 업데이트해야할 때
  359 +user.update( (user) { // 이 parameter는 업데이트 하길 원하는 인스턴스 자체입니다.
364 user.name = 'Jonny'; 360 user.name = 'Jonny';
365 user.age = 18; 361 user.age = 18;
366 }); 362 });
367 -// an alternative way of update the user variable: 363 +// user 인스턴스를 업데이트하는 또다른 방법
368 user(User(name: 'João', age: 35)); 364 user(User(name: 'João', age: 35));
369 365
370 // on view: 366 // on view:
371 Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}")) 367 Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}"))
372 -// you can also access the model values without the .value:  
373 -user().name; // notice that is the user variable, not the class (variable has lowercase u) 368 +// .value 없이 model의 value에 접근할 수 있습니다.
  369 +user().name; // User 클래스가 아니라, user 변수임을 주의하세요 (변수는 소문자 u를 갖고 있습니다.)
374 ``` 370 ```
375 371
376 -You don't have to work with sets if you don't want to. you can use the "assign 'and" assignAll "api.  
377 -The "assign" api will clear your list, and add a single object that you want to start there.  
378 -The "assignAll" api will clear the existing list and add any iterable objects that you inject into it. 372 +원하지 않으면 set을 이용하지 않아도 됩니다. "assign"과 "assignAll" api를 이용할 수 있습니다.
  373 +"assign" api는 당신의 리스트를 비우고, 채우고 싶은 하나의 요소를 넣을 수 있습니다.
  374 +"assignAll" api는 존재하는 리스트를 비우고, 삽입하길 원하는 iterable 객체들을 추가할 수 있습니다.
379 375
380 -### Why i have to use .value 376 +### 어째서 .value를 사용하는가
381 377
382 -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. 378 +code generator와 decoration을 이용하면 `String`과 `int`와 같은 타입에도 '.value'를 이용하지 않아도 되었겠지만, 이 라이브러리의 목표는 외부 종속성을 피하는 것입니다. 우리는 외부 패키지를 이용하지 않고, 간단하고 가벼우며 성능좋은 필수요소들(라우트 관리, 종속성 관리, 상태 관리)을 제공하고, 쾌적한 프로그래밍 환경을 제공하고 싶었습니다.
383 379
384 -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. 380 +단 3글자(get)와 콜론(;)만 pubspec에 적고 프로그래밍을 시작하세요. 모든 솔루션들이 기본적으로 제공되며, 쉽고 생산성과 성능 좋게 라우트와 상태 관리를 할 수 있습니다.
385 381
386 -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. 382 +이 라이브러리는 완벽한 솔루션임에도 불구하고 단일 상태 관리 패키지보다 가볍습니다. 이 점을 꼭 아셔야 합니다.
387 383
388 -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. 384 +만약 `.value`가 code generator처럼 당신을 괴롭힌다면, MobX가 훌륭한 대안으로 Get과 함께 활용할 수 있습니다. pubspec에서 단일 종속성을 원하고, 호환되지 않는 버전의 패키지들을 걱정하지 않고 프로그래밍을 시작하길 원하거나, 상태 업데이트 오류가 상태 관리자나 패키지에서 비롯되는 경우, controller에 사용가능성에 대한 걱정하기 원하지 않고 말그대로 "프로그래밍만"을 하고 싶은 경우, get은 완벽한 방안입니다.
389 385
390 -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. 386 +당신이 MobX의 code generator를 이용하는데 문제가 없었거나 BloC의 boilerplate를 이용하는데 문제가 없었다면, Get을 라우트하는데 쉽게 사용할 수 있을 것이며 상태 관리자를 갖고 있다는 사실을 잊을 것입니다. Get의 SEM과 RSM은 필수적으로 탄생했습니다. 저희 회사에는 90개의 controller가 넘는 프로젝트가 있었는데, 충분히 좋은 디바이스에서도 flutter clean 이후, code generator는 작업을 끝내는데 30분 이상이 걸렸습니다. 당신의 프로젝트에 5, 10, 15개 정도의 controller들만 있다면 어떤 상태 관리자들도 충분히 좋겠지만, 엄청 큰 프로젝트를 진행하고 있다면 code generator는 문제를 일으킬 것입니다. get은 매우 훌륭한 해결책입니다.
391 387
392 -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. 388 +누군가 이 프로젝트에 기여하고자 code generator나 비슷한 것을 만들고 있다면, 저는 이 readme로 링크시키겠습니다. 저한테 필요한 것들이 모든 개발자에게 필요한 것들은 아니겠지만, 지금으로써는 MobX와 같은 좋은 솔루션들이 있다고 말할 수 있습니다.
393 389
394 ### Obx() 390 ### Obx()
395 391
396 -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.  
397 -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. 392 +바인딩을 이용해 Get을 입력하는 것은 불필요합니다. 익명 함수만 받는 GetX 대신 Obx 위젯을 이용할 수 있습니다. 타입을 이용하지 않는다면, 변수를 사용하기 위한 controller 객체를 이용하거나, `Get.find<Controller>().value` 혹은 `Controller.to.value`를 이용하여 value에 접근하면 됩니다.
398 393
399 ### Workers 394 ### Workers
400 395
401 -Workers will assist you, triggering specific callbacks when an event occurs. 396 +Worker는 이벤트가 일어났을 때, 특정 콜백함수들을 호출하는 것을 도와줍니다.
402 397
403 ```dart 398 ```dart
404 -/// Called every time `count1` changes. 399 +/// 'count1'이 변경될 때마다 호출
405 ever(count1, (_) => print("$_ has been changed")); 400 ever(count1, (_) => print("$_ has been changed"));
406 401
407 -/// Called only first time the variable $_ is changed 402 +/// 'count1'이 처음으로 변경될 때 호출
408 once(count1, (_) => print("$_ was changed once")); 403 once(count1, (_) => print("$_ was changed once"));
409 404
410 -/// Anti DDos - Called every time the user stops typing for 1 second, for example. 405 +/// Anti DDos - 'count1'이 변경되고 1초간 변화가 없을 때 호출
411 debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1)); 406 debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1));
412 407
413 -/// Ignore all changes within 1 second. 408 +/// 'count1'이 변경되고 있는 동안 1초 간격으로 호출
414 interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1)); 409 interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
415 ``` 410 ```
416 -All workers (except `debounce`) have a `condition` named parameter, which can be a `bool` or a callback that returns a `bool`.  
417 -This `condition` defines when the `callback` function executes. 411 +(`debounce`를 제외한)모든 worker들은 `condition` parameter를 가집니다. 이 parameter는 `bool` 이거나 `bool`을 return 하는 콜백함수입니다. 이 `condition`은 `callback` 함수가 언제 실행될지 정의합니다.
418 412
419 -All workers returns a `Worker` instance, that you can use to cancel ( via `dispose()` ) the worker. 413 +모든 worker들은 `Worker` 객체를 return하며, `dispose()`를 이용하여 worker 동작을 취소시킬 수 있습니다.
420 414
421 - **`ever`** 415 - **`ever`**
422 - is called every time the _Rx_ variable emits a new value. 416 +_Rx_ 변수가 바뀔 때마다 항상 호출됩니다.
423 417
424 - **`everAll`** 418 - **`everAll`**
425 - Much like `ever`, but it takes a `List` of _Rx_ values Called every time its variable is changed. That's it.  
426 - 419 +`ever`처럼, `List` _Rx_ 변수가 주어지고 변경될 때마다 호출됩니다.
427 420
428 - **`once`** 421 - **`once`**
429 -'once' is called only the first time the variable has been changed. 422 +변수가 최초로 변경될 때(한 번만) 호출됩니다.
430 423
431 - **`debounce`** 424 - **`debounce`**
432 -'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. 425 +'debounce'는 검색 함수를 구현하는 데에 매우 유용합니다. API 호출을 타이핑이 모두 끝났을 때만 호출 시킬 수 있습니다. 만약 사용자가 "진탁"을 타이핑한다면, 당신은 'ㅈ,ㅣ,ㄴ,ㅌ,ㅏ,ㄱ'에 해당하는 6번의 검색을 해야할 것입니다. Get을 이용하면 이런 일은 일어나지 않을 것입니다. 왜냐하면 "debounce" Worker는 타이핑이 끝났을 때에만 검색하도록 만들어주기 때문입니다.
433 426
434 - **`interval`** 427 - **`interval`**
435 -'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. 428 +'interval'은 debounce와 다릅니다. 사용자가 1초에 1000번의 변화를 주는 행동을 한다고 해봅시다. debounce는 마지막 변화가 있은 후, 정해진 시간(기본적으로는 800ms)이 지나면 한 번만 호출됩니다. interval은 정해진 시간동안 사용자의 행동들을 무시합니다. 사용자가 1분동안 1초에 1000번의 변화를 주는 행동을 지속한다면, debounce는 사용자가 행동을 멈춘 후 한 번만 호출됩니다. 1초로 time이 설정된 interval은 매 초마다 1번씩 총 60번 호출되며, 3초로 time이 설정된 interval은 3초마다 1번씩 총 20번 호출 될 것입니다. interval은 엄청 빠른 터치(클릭)를 이용한 어뷰징(abusing)을 막는데 사용하는 데에 사용하기를 추천합니다.(예를 들어 특정 버튼을 눌러 코인을 얻는다고 해봅시다. 1분에 300번의 터치를 한다면, 사용자는 1분에 300코인을 얻을 것입니다. 하지만 interval를 이용하여 3초를 time으로 설정하면 사용자가 300번을 터치하든, 수 천번을 터치하든지 간에 20코인밖에 얻지 못할 것입니다.) 검색과 같이 변화가 api를 통해 쿼리를 호출해야 하는 경우, debounce는 DDos 공격을 막는데 효과적입니다. debounce는 사용자가 타이핑을 멈추길 기다리고, 멈추면 호출되기 때문입니다. 위쪽의 코인 시나리오에 대입해서 생각해보면, 터치를 "멈춘" 때, 코인 1개만 얻을 수 있을 것입니다.
  429 +
436 430
437 -- 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).  
438 431
439 -## Simple State Manager 432 +- 참고: Worker는 Controller 혹은 클래스를 시작할 때만 사용할 수 있습니다. 그래서 항상 onInit 내에 있거나(권장사항), 클래스 생성자, StatefulWidget의 initState 안에(권장하지는 않지만 부작용은 없습니다.) 있어야 합니다.
440 433
441 -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. 434 +## 간단한 상태 관리자
442 435
443 -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. 436 +Get은 ChangeNotifier를 사용하지 않고, 엄청나게 가볍고 사용하기 쉬운 상태 관리자를 제공합니다. 이 상태 관리자는 Flutter가 처음인 사람들의 요구를 충족하며 대규모 어플리케이션에서도 문제를 발생시키지 않습니다.
444 437
445 -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. 438 +GetBuilder는 여러 상태 컨트롤을 정확하게 해내는 것을 목표로 합니다. 장바구니에 30개의 상품이 있고, 사용자가 하나를 삭제하기 위해 터치(클릭)하면 상품 목록이 업데이트 되어 가격과 품목 수가 줄어든다고 해봅시다. 이런 상황에서 GetBuilder는 매우 유용합니다. 왜냐하면 상태들을 그룹화하여 "연산 로직"없이 한 번에 변경하기 때문입니다. GetBuilder는 이런 상황을 고려하여 만들어졌습니다. 일시적인 상태 변화를 위해 setState를 사용하면 되므로 상태 관리자가 필요없기 때문입니다.
446 439
447 -### Advantages 440 +이렇게 하면 개별적 controller를 원하는 경우, 각 ID를 할당해주거나 GetX를 사용할 수 있습니다. 어떤 것을 선택할지 당신에게 달려있지만 이 점을 기억하세요. "개별" 위젯이 많은 경우에는 GetX의 성능이 뛰어나고, 상태 변화가 여러 번 일어나는 경우에는 GetBuilder의 성능이 뛰어납니다.
448 441
449 -1. Update only the required widgets.  
450 442
451 -2. Does not use changeNotifier, it is the state manager that uses less memory (close to 0mb).  
452 443
453 -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. 444 +### 장점
454 445
455 -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. 446 +1. 필요한 위젯만 업데이트 해줍니다.
456 447
457 -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. 448 +2. ChangeNotifier를 사용하지 않고, 적은 메모리(거의 0mb)를 이용하여 상태 관리를 해줍니다.
458 449
459 -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. 450 +3. StatfulWidget을 이용 안 해도 됩니다! Get을 이용하면 더 이상 StatefulWidget이 필요 없습니다. 다른 상태 관리자들을 사용하면, Provider, BLoC, MobX Controller 등의 객체를 갖기 위해 StatefulWidget을 사용해야 합니다. appBar, Scaffold, 그리고 대부분의 위젯들이 StatelessWidget로 구성된 것을 생각해본 적이 있나요? Get은 이 부분도 해결해줍니다. 모든 것들을 Stateless로 만드세요. 하나의 위젯만 업데이트할 필요가 있다면, GetBuilder로 감싸면 해당 상태를 가질 수 있습니다.
460 451
461 -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). 452 +4. 당신의 프로젝트를 잘 정돈할 수 있습니다! Controller들은 UI내에 두지 않고, TextEditController나 다른 controller 들을 당신의 Controller 클래스 내에 두세요!
462 453
463 -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. 454 +5. 렌더링 된 직후, 위젯을 업데이트하기 위해 이벤트를 발생시킬 필요가 있나요? GetBuilder는 StatefulWidget처럼 "initState"를 갖고 있습니다. 그리고 controller로부터 직접적으로 이벤트를 호출하고, 더 이상 이벤트를 initState내에 배치할 필요가 없습니다.
464 455
465 -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. 456 +6. timers 등과 같은 streams를 닫는 행동을 트리거해야 하나요? GetBuilder는 dispose 또한 갖고 있어서, 위젯이 없어지자마자 dispose를 호출할 수 있습니다.
466 457
467 -### Usage 458 +7. streams는 정말 필요할 때만 사용하세요. StreamController와 StreamBuilder는 controller 안에 정상적으로 사용할 수 있습니다만! 기억하세요. stream은 메모리를 적당히 사용하지만, 남용해서는 안됩니다. 30개의 stream이 동시에 열려있다면 ChangeNotifier보다 안좋습니다(ChangeNotifier는 매우 나쁩니다).
  459 +
  460 +8. RAM의 소모 없이 위젯을 업데이트 하세요. Get은 GetBuilder의 creator ID만 저장하고 필요한 경우에만 해당 GetBuilder만 업데이트 합니다. 수천개의 GetBuilder가 있어도 get은 ID를 저장하는데 매우 적은 메모리를 사용합니다. 새 GetBuilder를 생성한다면, creator ID를 갖고 있는 GetBuilder의 상태를 공유합니다. 각 GetBuilder의 새 상태는 생성 되지 않기 때문에 큰 규모의 어플리케이션에서도 **많은** RAM 자원을 절약합니다. 기본적으로 당신의 어플리케이션은 전반적으로 Stateless 이고, 극히 일부의 위젯만 단일 상태를 가진 (GetBuilder를 포함한)Stateful일 것이기 때문에, 하나의 업데이트만으로 그것들을 전부 업데이트 합니다. 상태는 단 하나뿐입니다.
  461 +
  462 +9. Get은 전지적으로 대부분의 경우 어느 타이밍에 메모리에서 제거해야할 지 알 고 있습니다. 당신은 언제 컨트롤러를 dispose해야하는지만 걱정하세요.
  463 +
  464 +### 사용법
468 465
469 ```dart 466 ```dart
470 -// Create controller class and extends GetxController 467 +// GetxController를 상속(extends)하는 controller 클래스를 만드세요
471 class Controller extends GetxController { 468 class Controller extends GetxController {
472 int counter = 0; 469 int counter = 0;
473 void increment() { 470 void increment() {
474 counter++; 471 counter++;
475 - update(); // use update() to update counter variable on UI when increment be called 472 + update(); // increment()가 호출되었을 때, counter 변수가 변경되어 UI에 반영되어야 한다는 것을 update()로 알려주세요
476 } 473 }
477 } 474 }
478 -// On your Stateless/Stateful class, use GetBuilder to update Text when increment be called 475 +// 당신의 Stateless/Stateful 클래스에서, increment()가 호출되었을 때 GetBuilder를 이용해 Text를 업데이트 하세요
479 GetBuilder<Controller>( 476 GetBuilder<Controller>(
480 - init: Controller(), // INIT IT ONLY THE FIRST TIME 477 + init: Controller(), // 맨 처음만! 초기화(init)해주세요
481 builder: (_) => Text( 478 builder: (_) => Text(
482 '${_.counter}', 479 '${_.counter}',
483 ), 480 ),
484 ) 481 )
485 -//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. 482 +
  483 +// controller는 처음만 초기화하면 됩니다. 같은 controller로 GetBuilder를 또 사용하려는 경우에는 init을 하지 마세요.
  484 +// 중복으로 'init'이 있는 위젯이 배치되자마자, controller는 자동적으로 메모리에서 제거될 것입니다.
  485 +// 걱정하실 필요 없이, Get은 자동적으로 controller를 찾아서 해줄겁니다. 그냥 2번 init하지 않는 것만 하시면 됩니다.
486 ``` 486 ```
487 487
488 -**Done!** 488 +**끝입니다!**
489 489
490 -- You have already learned how to manage states with Get. 490 +- 당신은 이미 Get을 이용하여 상태관리를 어떻게 하는지 다 배우셨어요!
491 491
492 -- 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. 492 +- 참고: 큰 규모의 프로젝트를 진행하면서 init 속성을 사용하지 않을 수도 있습니다. 그럴 때에는, Binding 클래스를 상속(extends)한 클래스를 만들고, 그 클래스 내에서 해당 라우트에 생성되어야 하는 controller를 선언하세요. controller가 즉각적으로 만들어지지는 않지만, controller가 처음 사용될 때 Get이 알아서 잘 만들어줄 것입니다. Get은 lazyLoad를 지원하며, controller가 더 이상 필요하지 않을 때 dispose를 해줍니다. 사용예제는 pub.dev에서 확인하세요.
493 493
494 -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): 494 +수많은 라우트를 진행하면서 예전에 사용하였던 controller의 데이터가 필요하면, GetBuilder를 다시 사용하시면 됩니다 (init 없이):
495 495
496 ```dart 496 ```dart
497 class OtherClass extends StatelessWidget { 497 class OtherClass extends StatelessWidget {
@@ -510,14 +510,17 @@ class OtherClass extends StatelessWidget { @@ -510,14 +510,17 @@ class OtherClass extends StatelessWidget {
510 510
511 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>()`) 511 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>()`)
512 512
  513 +GetBuilder 밖의 여러 곳에서 controller를 사용해야 하는 경우, 간단하게 Controller 클래스 안의 getter로 접근할 수 있습니다. (아니면 `Get.find<Controller>()`를 사용하세요)
  514 +
513 ```dart 515 ```dart
514 class Controller extends GetxController { 516 class Controller extends GetxController {
515 517
516 - /// You do not need that. I recommend using it just for ease of syntax.  
517 - /// with static method: Controller.to.counter();  
518 - /// with no static method: Get.find<Controller>().counter();  
519 - /// 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.  
520 - static Controller get to => Get.find(); // add this line 518 + /// 꼭 이렇게 할 필요는 없지만, 문법적으로 용이하게 사용하게 위해 이렇게 하시기를 권장합니다.
  519 + /// static 메소드로 사용할 경우: Controller.to.counter();
  520 + /// static 메소드로 사용하지 않을 경우: Get.find<Controller>().counter();
  521 + /// 이 둘 간의 성능적 차이는 없으며, 문법적 차이로 오는 부작용도 없습니다.
  522 + /// 단순히 하나는 type을 적을 필요가 없고, 다른 하나는 IDE가 자동완성 해준다는 차이점밖에 없습니다.
  523 + static Controller get to => Get.find(); // 이 코드만 추가하세요
521 524
522 int counter = 0; 525 int counter = 0;
523 void increment() { 526 void increment() {
@@ -527,7 +530,7 @@ class Controller extends GetxController { @@ -527,7 +530,7 @@ class Controller extends GetxController {
527 } 530 }
528 ``` 531 ```
529 532
530 -And then you can access your controller directly, that way: 533 +그리고 아래와 같은 방법으로, controller에 바로 접근하세요:
531 534
532 ```dart 535 ```dart
533 FloatingActionButton( 536 FloatingActionButton(
@@ -538,24 +541,22 @@ FloatingActionButton( @@ -538,24 +541,22 @@ FloatingActionButton(
538 ), 541 ),
539 ``` 542 ```
540 543
541 -When you press FloatingActionButton, all widgets that are listening to the 'counter' variable will be updated automatically. 544 +FloatingActionButton을 눌렀을 때, counter 변수를 주시(listen)하고 있는 위젯은 자동적으로 업데이트됩니다.
542 545
543 -### How it handles controllers 546 +### controller의 동작 방식
544 547
545 -Let's say we have this: 548 +아래와 같은 상황을 가정해보겠습니다:
546 549
547 -`Class a => Class B (has controller X) => Class C (has controller X)` 550 +`Class A => Class B (has controller X) => Class C (has controller X)`
548 551
549 -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. 552 +A 클래스에서 controller를 아직 사용하지 않았기 때문에, controller는 메모리에 없습니다(Get은 lazyLoad를 지원합니다). B 클래스에서는 controller를 사용하기 때문에 메모리에 로드됩니다. C 클래스에서는 B 클래스에서 사용한 controller와 같은 controller를 사용하기 때문에, Get은 B의 controller와 C의 controller의 상태를 공유하며, 그 동일한 controller는 여전히 메모리에 있습니다. 그리고 C 화면과 B 화면을 닫으면, Get은 자동적으로 controller X (B와 C에서 쓰인 controller)를 메모리에서 해제해줄 것입니다. 왜냐하면 A 클래스에서는 controller X를 사용하지 않기 때문이죠. 만약 B 화면으로 라우팅한다면 controller X는 다시 메모리에 로드됩니다. 그리고 C 화면으로 라우팅되는 대신, A 화면으로 되돌아간다면 같은 방식으로 controller X는 메모리에서 해제됩니다. 만약 클래스 C에서 controller를 사용하지 않고, 클래스 B가 메모리에서 해제된다면, controller를 사용하는 클래스가 없기 때문에 같은 방식으로 controller는 메모리에서 해제됩니다. Get이 에러날 수 있는 유일한 예외 상황은 B가 예기치않게 라우트 상에서 제거되고, C에서 controller를 사용하려고 하는 경우입니다. 이 경우, B에 있던 controller의 creator ID가 제거되는데, Get은 creator ID를 갖고 있지 않은 controller는 메모리에서 제거하도록 프로그래밍되어 있습니다. 이런 일을 원하지 않으신다면, "authoRemove: false" 플래그를 B 클래스의 GetBuilder에 추가하고, "assignId: true"를 C 클래스의 GetBuilder에 추가해주세요.
550 553
551 -### You won't need StatefulWidgets anymore 554 +### StatefulWidget을 더 이상 사용할 필요없습니다
552 555
553 -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.  
554 -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!  
555 -Unless you need to use a mixin, like TickerProviderStateMixin, it will be totally unnecessary to use a StatefulWidget with Get. 556 +SatefullWidget을 사용한다는 것은 위젯을 최소한으로 재빌드해야하는 경우에도, 위젯을 Consumer / Oberver / BlocProvider / GetBuilder / GetX / Obx 안에 넣어줄 것이기 때문에, 또다른 StatefulWidget을 사용하는 것과 마찬가지이므로 화면 전체의 상태를 불필요하게 저장합니다. StatefulWidget 클래스는 StatelessWidget 클래스보다 더 많은 RAM 할당이 필요한 큰 규모의 클래스입니다. 1개나 2개 정도의 클래스라면 별 차이가 없겠지만, 100개 이상부터는 차이가 있을 것입니다! TickerProviderStateMixin과 같은 mixin이 필요없는 경우, Get을 사용하면 StatefulWidget은 필요 없습니다.
556 557
557 -You can call all methods of a StatefulWidget directly from a GetBuilder.  
558 -If you need to call initState() or dispose() method for example, you can call them directly; 558 +StatefulWidget에서 메소드를 직접적으로 호출하는 것처럼, Getbuilder를 통해 메소드를 호출할 수 있습니다.
  559 +initState()나 dispose()를 호출할 필요가 있을 때에도, 직접적으로 호출할 수 있습니다.
559 560
560 ```dart 561 ```dart
561 GetBuilder<Controller>( 562 GetBuilder<Controller>(
@@ -565,7 +566,7 @@ GetBuilder<Controller>( @@ -565,7 +566,7 @@ GetBuilder<Controller>(
565 ), 566 ),
566 ``` 567 ```
567 568
568 -A much better approach than this is to use the onInit() and onClose() method directly from your controller. 569 +위 방법보다 더 좋은 방법은 Controller에서 onInit()과 onClose()를 이용하는 것입니다.
569 570
570 ```dart 571 ```dart
571 @override 572 @override
@@ -575,24 +576,22 @@ void onInit() { @@ -575,24 +576,22 @@ void onInit() {
575 } 576 }
576 ``` 577 ```
577 578
578 -- 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. 579 +- 참고: controller가 처음 불려졌을 때 어떤 메소드가 호출되길 원하는 경우, (좋은 성능을 목표로하는 Get 패키지를 이용하면)이를 위해서 생성자를 **사용할 필요가 없습니다**. 생성자를 사용한다는 것은 controller가 생성되거나 할당되었을 때의 로직에서 벗어나는 일이기 때문에 좋지 않습니다. (controller 객체를 생성하려하면 생성자는 즉시 호출되며, controller를 사용하기 이전부터 메모리에 로드됩니다. 이러한 동작은 이 라이브러리의 성능을 저해합니다.) onInit()과 onClose()는 이를 위해 만들어졌습니다. Get.lazyPut하는지 여부에 따라, controller가 생성되거나 처음 사용될 때 onInit()과 onClose()가 호출됩니다. API를 호출하기 위한 데이터를 초기화 등을 위해 구식 방식의 initState/dispose를 사용하는 대신 onInit()을 사용하고, stream을 닫는 등의 동작이 필요하면 onClose()를 사용하세요.
579 580
580 -### Why it exists 581 +### 이 패키지의 목표
581 582
582 -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. 583 +이 패키지의 목표는 당신에게 최소의 종속성(pubspec의 dependencies)으로 라우트/상태/종속성 관리를 위한 완전한 솔루션을 제공하는 것입니다. Get은 어떤 종속성에서도, 어떤 버전의 Flutter API를 사용하더라도 동작하도록 보장해줍니다. 어떤 종속성에서도 당신의 프로젝트가 동작하도록 단일 패키지로 모든 것을 집약하였습니다. 이런 방법으로 당신은 화면상 위젯들만 신경쓰고, 팀원 중 일부는 비즈니스 로직에만 신경쓸 수 있도록 하였습니다. 이 점은 당신에게 더 나은 작업환경을 제공합니다. 팀원 중 일부는 controller에 보내지는 데이터에 신경 쓰지 않고 위젯에만 집중하고, 다른 팀원들은 위젯 배치에는 신경쓰지 않고 비즈니스 로직에만 집중하여 작업할 수 있습니다.
583 584
584 -So to simplify this:  
585 -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.  
586 -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. 585 +간단히 말하면: 여러 메소드들을 initState에서 호출할 필요도 없고, 메소드들을 parameter로 controller에 넘겨줄 필요 없고, controller 생성자를 호출할 필요도 없습니다. 여러분의 서비스가 시작하고 호출되는 onInit()를 이용하면 됩니다. 그리고 controller가 더 이상 필요 없을 때 메모리에서 제거 될 때 호출되는 onClose()를 이용하세요. 이 방법으로 화면 구성은 위젯 배치만 신경써도 되게 해줍니다.
587 586
588 -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: 587 +GetxController 안에서 dispose를 호출하지 마세요. 아무동작도 하지 않을 뿐더러 controller는 위젯이 아니기 때문에 "dispose"할 수 없다는 점을 기억하세요. Get에 의해 자동적으로 똑똑하게 메모리에서 해제 될 것입니다. 만약 stream들을 닫고 싶다면 onClose() 메소드 안에서 닫아주세요. 예를 들어:
589 588
590 ```dart 589 ```dart
591 class Controller extends GetxController { 590 class Controller extends GetxController {
592 StreamController<User> user = StreamController<User>(); 591 StreamController<User> user = StreamController<User>();
593 StreamController<String> name = StreamController<String>(); 592 StreamController<String> name = StreamController<String>();
594 593
595 - /// close stream = onClose method, not dispose. 594 + /// dispose가 아니라 onClose()에서 stream을 닫으세요
596 @override 595 @override
597 void onClose() { 596 void onClose() {
598 user.close(); 597 user.close();
@@ -602,121 +601,120 @@ class Controller extends GetxController { @@ -602,121 +601,120 @@ class Controller extends GetxController {
602 } 601 }
603 ``` 602 ```
604 603
605 -Controller life cycle: 604 +Controller 생명 주기:
606 605
607 -- onInit() where it is created.  
608 -- onClose() where it is closed to make any changes in preparation for the delete method  
609 -- 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. 606 +- onInit()은 생성되었을 때 호출
  607 +- onClose()는 delete 메소드를 준비하기 위해 닫히는 경우
  608 +- deleted: controller가 메모리에서 해제되어 더 이상 API에 접근할 수 없을 때. 말 그대로 삭제되어 추적할 수 없습니다.
610 609
611 -### Other ways of using it 610 +### 다른 사용법
612 611
613 -You can use Controller instance directly on GetBuilder value: 612 +Controller 객체를 GetBuilder 안에서 value로 직접 접근할 수 있습니다:
614 613
615 ```dart 614 ```dart
616 GetBuilder<Controller>( 615 GetBuilder<Controller>(
617 init: Controller(), 616 init: Controller(),
618 builder: (value) => Text( 617 builder: (value) => Text(
619 - '${value.counter}', //here 618 + '${value.counter}', // 여기!
620 ), 619 ),
621 ), 620 ),
622 ``` 621 ```
623 622
624 -You may also need an instance of your controller outside of your GetBuilder, and you can use these approaches to achieve this: 623 +GetBuilder 바깥에서도 controller 객체가 필요하면, 다음과 같이 접근할 수 있습니다:
625 624
626 ```dart 625 ```dart
627 class Controller extends GetxController { 626 class Controller extends GetxController {
628 static Controller get to => Get.find(); 627 static Controller get to => Get.find();
629 [...] 628 [...]
630 } 629 }
631 -// on you view: 630 +// 화면상
632 GetBuilder<Controller>( 631 GetBuilder<Controller>(
633 - init: Controller(), // use it only first time on each controller 632 + init: Controller(), // 각 controller를 처음 사용할 때 init 하세요
634 builder: (_) => Text( 633 builder: (_) => Text(
635 - '${Controller.to.counter}', //here 634 + '${Controller.to.counter}', // 여기!
636 ) 635 )
637 ), 636 ),
638 ``` 637 ```
639 638
640 -or 639 +아니면
641 640
642 ```dart 641 ```dart
643 class Controller extends GetxController { 642 class Controller extends GetxController {
644 - // static Controller get to => Get.find(); // with no static get 643 + // static Controller get to => Get.find(); // static get 없이
645 [...] 644 [...]
646 } 645 }
647 -// on stateful/stateless class 646 +// stateless/stateful 클래스에서
648 GetBuilder<Controller>( 647 GetBuilder<Controller>(
649 - init: Controller(), // use it only first time on each controller 648 + init: Controller(), // 각 controller를 처음 사용할 때 init 하세요
650 builder: (_) => Text( 649 builder: (_) => Text(
651 - '${Get.find<Controller>().counter}', //here 650 + '${Get.find<Controller>().counter}', // 여기!
652 ), 651 ),
653 ), 652 ),
654 ``` 653 ```
655 654
656 -- 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: 655 +- "비표준"적인 방식의 접근도 다음과 같이 가능합니다. get_it, modular 등과 같은 다른 종속성 관리자를 사용한다면, 아래와 같이 controller 객체를 전달해줄 수 있습니다:
657 656
658 ```dart 657 ```dart
659 Controller controller = Controller(); 658 Controller controller = Controller();
660 [...] 659 [...]
661 GetBuilder<Controller>( 660 GetBuilder<Controller>(
662 - init: controller, //here 661 + init: controller, // 여기!
663 builder: (_) => Text( 662 builder: (_) => Text(
664 - '${controller.counter}', // here 663 + '${controller.counter}', // 여기!
665 ), 664 ),
666 ), 665 ),
667 666
668 ``` 667 ```
669 668
670 -### Unique IDs 669 +### 고유 ID
671 670
672 -If you want to refine a widget's update control with GetBuilder, you can assign them unique IDs: 671 +GetBuilder로 위젯의 업데이트를 좀 더 세분화하여 다루고 싶다면, 고유 ID를 부여하세요:
673 672
674 ```dart 673 ```dart
675 GetBuilder<Controller>( 674 GetBuilder<Controller>(
676 id: 'text' 675 id: 'text'
677 - init: Controller(), // use it only first time on each controller 676 + init: Controller(), // 각 controller를 처음 사용할 때 init 하세요
678 builder: (_) => Text( 677 builder: (_) => Text(
679 - '${Get.find<Controller>().counter}', //here 678 + '${Get.find<Controller>().counter}', // 여기!
680 ), 679 ),
681 ), 680 ),
682 ``` 681 ```
683 682
684 -And update it this form: 683 +그리고 다음과 같이 update 하세요:
685 684
686 ```dart 685 ```dart
687 update(['text']); 686 update(['text']);
688 ``` 687 ```
689 688
690 -You can also impose conditions for the update: 689 +또, update하는데 조건도 줄 수 있습니다:
691 690
692 ```dart 691 ```dart
693 update(['text'], counter < 10); 692 update(['text'], counter < 10);
694 ``` 693 ```
695 694
696 -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). 695 +GetX는 위젯이 정말 값이 변경되었을 때에만 재빌드합니다. 만약 변수의 값이 전과 같은 값으로 변경되었다면, GetX는 메모리와 CPU 자원을 아끼기 위해 재빌드하지 않습니다.(화면에 3이라는 숫자가 보여지고 있고, 그 숫자가 다시 3으로 변경된 경우를 가정하겠습니다. 대부분의 상태 관리자들은 이러한 경우에 재빌드를 합니다만, GetX를 사용하면 정말 값이 변경되었을 때에만 재빌드를 합니다.)
697 696
698 -## Mixing the two state managers 697 +## 2개의 상태 관리자 섞어쓰기
699 698
700 -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. 699 +단 하나의 반응변수(.obs)와 다른 메커니즘(update())가 모두 필요해서 Getbuilder 안에 Obx를 넣어야 하는 경우가 필요했습니다. 이 경우를 위해 MixinBuilder가 만들어졌습니다. ".obs"변수의 값이 바뀔 때 즉각적으로 바뀌는 것과 update()를 통해 바뀌는 것 모두를 지원합니다. 하지만, 이 위젯이 GetBuilder, GetX, Obx 보다 더 많은 리소스를 필요로합니다. 왜냐하면 controller의 update() 메소드와 자식으로부터의 .obs 변수의 변화를 주시하고 있어야 하기 때문입니다.
701 700
702 -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. 701 +GetxController를 상속(extends)하는 것은 중요합니다. onInit()과 onClose()에서 "시작"과 "종료" 이벤트를 수행할 수 있는 생명 주기를 갖고 있기 때문입니다. 이를 위해서 어떤 클래스를 사용해도 괜찮지만, obervable한 변수든 아니든 간에 GetXController를 사용해 변수를 다루길 적극 권장합니다.
703 702
704 703
705 ## GetBuilder vs GetX vs Obx vs MixinBuilder 704 ## GetBuilder vs GetX vs Obx vs MixinBuilder
706 705
707 -In a decade working with programming I was able to learn some valuable lessons. 706 +10년간 프로그래밍을 하며 일해오면서, 귀중한 교훈을 얻을 수 있었습니다.
708 707
709 -My first contact with reactive programming was so "wow, this is incredible" and in fact reactive programming is incredible.  
710 -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. 708 +반응형 프로그래밍을 처음 접했을 때 "와, 진짜 굉장한데!"라고 느꼈고, 실제로도 반응형 프로그래밍은 정말 놀랍습니다. 하지만, 모든 상황에서 올바르지는 않습니다. 많은 경우 2개내지 3개의 위젯의 상태를 동시에 변경하거나 일시적으로 변경해야하는데, 반응형 프로그래밍은 나쁘지 않지만 적적하지 않습니다.
711 709
712 -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. 710 +반응형 프로그래밍은 각각의 워크플로우를 위한 RAM 자원을 많이 필요로 합니다. 하나의 위젯만이 재빌드 되어야 하는 경우는 괜찮지만, 리스트에 80개 가량의 요소가 있고, 각각 stream이 있을 경우에는 좋지 않습니다. dart inspect 창을 열고 StreamBuilder가 얼마나 많은 리소스를 사용하는지 보신다면, 제 말이 이해가 가실겁니다.
713 711
714 -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. 712 +이런 생각에, 저는 간단한 상태 관리자를 만들었습니다. 간단합니다. 그리고 이것이 여러분이 정말 요구하는 것이에요: 블록 단위로 매우 경제적이고 간단하게 상태를 업데이트합니다.
715 713
716 -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). 714 +`GetBuilder`는 RAM의 측면에서 가장 경제적입니다. 이보다 더 경제적인 방법은 없을 겁니다(만약 그런 방법을 고안하신다면, 꼭 저희에게 알려주세요!)
717 715
718 -However, GetBuilder is still a mechanical state manager, you need to call update() just like you would need to call Provider's notifyListeners(). 716 +하지만 `GetBuilder`는 수동적인 상태 관리자입니다. Provider의 notifyListeners()를 호출하는 것처럼 update()를 호출해야만 합니다.
719 717
720 -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. 718 +반응형 프로그래밍이 정말 도움이 되는 상황들이 많습니다. 이를 활용하지 않는건 바퀴를 다시 만드는 것과 마찬가지입니다. 이런 생각에, `GetX`는 상태 관리자로 가장 현대적이고 높은 수준의 기능들을 제공하기 위해 만들어졌습니다. 이것은 필요한 것들을 필요한 때에 업데이트합니다. 만약 에러가 있고 300개의 상태가 동시에 변경되면, `GetX`는 화면상에 반영되어야할 것들만 필터링하여 업데이트 합니다.
721 719
722 -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. 720 +`GetX`는 다른 반응형 상태 관리자들보다 경제적이지만, `GetBuiler`보다 조금 더 RAM을 소모합니다. 능동적이면서 RAM의 최대한 효율적으로 사용하기 위해 `Obx`가 만들어졌습니다. `GetX`와 `GetBuilder`와 다르게 `Obx`안에서 controller를 초기화할 수 없습니다. 단지 자식으로부터 변화를 감지하는 StreamSubscription을 갖고 있는 위젯일 뿐입니다. `Obx`는 `GetX`보다는 경제적이지만 `GetBuilder`보다는 덜 경제적입니다. 왜냐하면 `Obx`는 반응적이고, `GetBuilder`는 위젯의 해시코드와 StateSetter만 저장하는 최적의 접근 방식을 갖고 있기 때문입니다. `Obx`를 이용하면 controller의 타입을 적어줄 필요가 없고, 여러 개의 다른 controller 변화를 감지합니다. 하지만 사용 전에 초기화거나, readme에 있는 예제처럼 사용하거나, Binding 클래스를 사용해야 합니다.
@@ -83,9 +83,9 @@ Nesses casos pode ser usado o lazyPut que só cria a instância no momento que e @@ -83,9 +83,9 @@ Nesses casos pode ser usado o lazyPut que só cria a instância no momento que e
83 Get.lazyPut<ApiMock>(() => ApiMock()); 83 Get.lazyPut<ApiMock>(() => ApiMock());
84 84
85 Get.lazyPut<FirebaseAuth>( 85 Get.lazyPut<FirebaseAuth>(
86 - () => { 86 + () {
87 // ... alguma lógica se necessário 87 // ... alguma lógica se necessário
88 - return FirebaseAuth() 88 + return FirebaseAuth();
89 }, 89 },
90 tag: Math.random().toString(), 90 tag: Math.random().toString(),
91 fenix: true 91 fenix: true
@@ -313,7 +313,7 @@ getPages: [ @@ -313,7 +313,7 @@ getPages: [
313 GetPage( 313 GetPage(
314 name: '/', 314 name: '/',
315 page: () => HomeView(), 315 page: () => HomeView(),
316 - binding: BindingsBuilder(() => { 316 + binding: BindingsBuilder(() {
317 Get.lazyPut<ControllerX>(() => ControllerX()); 317 Get.lazyPut<ControllerX>(() => ControllerX());
318 Get.put<Service>(()=> Api()); 318 Get.put<Service>(()=> Api());
319 }), 319 }),
@@ -321,7 +321,7 @@ getPages: [ @@ -321,7 +321,7 @@ getPages: [
321 GetPage( 321 GetPage(
322 name: '/detalhes', 322 name: '/detalhes',
323 page: () => DetalhesView(), 323 page: () => DetalhesView(),
324 - binding: BindingsBuilder(() => { 324 + binding: BindingsBuilder(() {
325 Get.lazyPut<DetalhesController>(() => DetalhesController()); 325 Get.lazyPut<DetalhesController>(() => DetalhesController());
326 }), 326 }),
327 ), 327 ),
@@ -195,12 +195,12 @@ Get.bottomSheet( @@ -195,12 +195,12 @@ Get.bottomSheet(
195 ListTile( 195 ListTile(
196 leading: Icon(Icons.music_note), 196 leading: Icon(Icons.music_note),
197 title: Text('Música'), 197 title: Text('Música'),
198 - onTap: () => {} 198 + onTap: () {}
199 ), 199 ),
200 ListTile( 200 ListTile(
201 leading: Icon(Icons.videocam), 201 leading: Icon(Icons.videocam),
202 title: Text('Vídeo'), 202 title: Text('Vídeo'),
203 - onTap: () => {}, 203 + onTap: () {},
204 ), 204 ),
205 ], 205 ],
206 ), 206 ),
@@ -81,9 +81,9 @@ Get.put<S>( @@ -81,9 +81,9 @@ Get.put<S>(
81 Get.lazyPut<ApiMock>(() => ApiMock()); 81 Get.lazyPut<ApiMock>(() => ApiMock());
82 82
83 Get.lazyPut<FirebaseAuth>( 83 Get.lazyPut<FirebaseAuth>(
84 - () => { 84 + () {
85 // ... some logic if needed 85 // ... some logic if needed
86 - return FirebaseAuth() 86 + return FirebaseAuth();
87 }, 87 },
88 tag: Math.random().toString(), 88 tag: Math.random().toString(),
89 fenix: true 89 fenix: true
@@ -309,7 +309,7 @@ getPages: [ @@ -309,7 +309,7 @@ getPages: [
309 GetPage( 309 GetPage(
310 name: '/', 310 name: '/',
311 page: () => HomeView(), 311 page: () => HomeView(),
312 - binding: BindingsBuilder(() => { 312 + binding: BindingsBuilder(() {
313 Get.lazyPut<ControllerX>(() => ControllerX()); 313 Get.lazyPut<ControllerX>(() => ControllerX());
314 Get.put<Service>(()=> Api()); 314 Get.put<Service>(()=> Api());
315 }), 315 }),
@@ -317,7 +317,7 @@ getPages: [ @@ -317,7 +317,7 @@ getPages: [
317 GetPage( 317 GetPage(
318 name: '/details', 318 name: '/details',
319 page: () => DetailsView(), 319 page: () => DetailsView(),
320 - binding: BindingsBuilder(() => { 320 + binding: BindingsBuilder(() {
321 Get.lazyPut<DetailsController>(() => DetailsController()); 321 Get.lazyPut<DetailsController>(() => DetailsController());
322 }), 322 }),
323 ), 323 ),
@@ -484,12 +484,12 @@ Get.bottomSheet( @@ -484,12 +484,12 @@ Get.bottomSheet(
484 ListTile( 484 ListTile(
485 leading: Icon(Icons.music_note), 485 leading: Icon(Icons.music_note),
486 title: Text('Music'), 486 title: Text('Music'),
487 - onTap: () => {} 487 + onTap: () {}
488 ), 488 ),
489 ListTile( 489 ListTile(
490 leading: Icon(Icons.videocam), 490 leading: Icon(Icons.videocam),
491 title: Text('Video'), 491 title: Text('Video'),
492 - onTap: () => {}, 492 + onTap: () {},
493 ), 493 ),
494 ], 494 ],
495 ), 495 ),
@@ -81,9 +81,9 @@ Get.put<S>( @@ -81,9 +81,9 @@ Get.put<S>(
81 Get.lazyPut<ApiMock>(() => ApiMock()); 81 Get.lazyPut<ApiMock>(() => ApiMock());
82 82
83 Get.lazyPut<FirebaseAuth>( 83 Get.lazyPut<FirebaseAuth>(
84 - () => { 84 + () {
85 // ... some logic if needed 85 // ... some logic if needed
86 - return FirebaseAuth() 86 + return FirebaseAuth();
87 }, 87 },
88 tag: Math.random().toString(), 88 tag: Math.random().toString(),
89 fenix: true 89 fenix: true
@@ -306,7 +306,7 @@ getPages: [ @@ -306,7 +306,7 @@ getPages: [
306 GetPage( 306 GetPage(
307 name: '/', 307 name: '/',
308 page: () => HomeView(), 308 page: () => HomeView(),
309 - binding: BindingsBuilder(() => { 309 + binding: BindingsBuilder(() {
310 Get.lazyPut<ControllerX>(() => ControllerX()); 310 Get.lazyPut<ControllerX>(() => ControllerX());
311 Get.put<Service>(()=> Api()); 311 Get.put<Service>(()=> Api());
312 }), 312 }),
@@ -314,7 +314,7 @@ getPages: [ @@ -314,7 +314,7 @@ getPages: [
314 GetPage( 314 GetPage(
315 name: '/details', 315 name: '/details',
316 page: () => DetailsView(), 316 page: () => DetailsView(),
317 - binding: BindingsBuilder(() => { 317 + binding: BindingsBuilder(() {
318 Get.lazyPut<DetailsController>(() => DetailsController()); 318 Get.lazyPut<DetailsController>(() => DetailsController());
319 }), 319 }),
320 ), 320 ),
@@ -478,12 +478,12 @@ Get.bottomSheet( @@ -478,12 +478,12 @@ Get.bottomSheet(
478 ListTile( 478 ListTile(
479 leading: Icon(Icons.music_note), 479 leading: Icon(Icons.music_note),
480 title: Text('Music'), 480 title: Text('Music'),
481 - onTap: () => {} 481 + onTap: () {}
482 ), 482 ),
483 ListTile( 483 ListTile(
484 leading: Icon(Icons.videocam), 484 leading: Icon(Icons.videocam),
485 title: Text('Video'), 485 title: Text('Video'),
486 - onTap: () => {}, 486 + onTap: () {},
487 ), 487 ),
488 ], 488 ],
489 ), 489 ),
  1 +const Map<String, String> en_US = {
  2 + 'covid': 'Corona Virus',
  3 + 'total_confirmed': 'Total Confirmed',
  4 + 'total_deaths': 'Total Deaths',
  5 + 'fetch_country': 'Fetch by country',
  6 + 'corona_by_country': 'Corona by country',
  7 + 'total_infecteds': 'Total Infecteds',
  8 + 'details': 'Details',
  9 + 'total_recovered': 'Total Recovered',
  10 +};
  1 +const Map<String, String> pt_BR = {
  2 + 'covid': 'Corona Vírus',
  3 + 'total_confirmed': 'Total confirmado',
  4 + 'total_deaths': 'Total de mortes',
  5 + 'fetch_country': 'Listar por país',
  6 + 'corona_by_country': 'Corona por país',
  7 + 'total_infecteds': 'Total de infectados',
  8 + 'details': 'Detalhes',
  9 + 'total_recovered': 'Total de recuperados'
  10 +};
  1 +import 'package:flutter/material.dart';
  2 +import 'package:get/get.dart';
  3 +
  4 +import 'en_US.dart';
  5 +import 'pt_BR.dart';
  6 +
  7 +class TranslationService extends Translations {
  8 + static final locale = Get.deviceLocale;
  9 + static final fallbackLocale = Locale('en', 'US');
  10 + @override
  11 + Map<String, Map<String, String>> get keys => {
  12 + 'en_US': en_US,
  13 + 'pt_BR': pt_BR,
  14 + };
  15 +}
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
  3 +import 'lang/translation_service.dart';
3 import 'routes/app_pages.dart'; 4 import 'routes/app_pages.dart';
4 import 'shared/logger/logger_utils.dart'; 5 import 'shared/logger/logger_utils.dart';
5 6
@@ -18,6 +19,9 @@ class MyApp extends StatelessWidget { @@ -18,6 +19,9 @@ class MyApp extends StatelessWidget {
18 logWriterCallback: Logger.write, 19 logWriterCallback: Logger.write,
19 initialRoute: AppPages.INITIAL, 20 initialRoute: AppPages.INITIAL,
20 getPages: AppPages.routes, 21 getPages: AppPages.routes,
  22 + locale: TranslationService.locale,
  23 + fallbackLocale: TranslationService.fallbackLocale,
  24 + translations: TranslationService(),
21 ); 25 );
22 } 26 }
23 } 27 }
@@ -22,7 +22,7 @@ class CountryView extends GetView<HomeController> { @@ -22,7 +22,7 @@ class CountryView extends GetView<HomeController> {
22 child: Scaffold( 22 child: Scaffold(
23 backgroundColor: Colors.transparent, 23 backgroundColor: Colors.transparent,
24 appBar: AppBar( 24 appBar: AppBar(
25 - title: Text("Corona By Country"), 25 + title: Text('corona_by_country'.tr),
26 backgroundColor: Colors.transparent, 26 backgroundColor: Colors.transparent,
27 elevation: 0, 27 elevation: 0,
28 centerTitle: true, 28 centerTitle: true,
@@ -43,7 +43,7 @@ class CountryView extends GetView<HomeController> { @@ -43,7 +43,7 @@ class CountryView extends GetView<HomeController> {
43 ), 43 ),
44 title: Text(country.country), 44 title: Text(country.country),
45 subtitle: 45 subtitle:
46 - Text("Total infecteds: ${country.totalConfirmed}"), 46 + Text('total_infecteds'.tr +' ${country.totalConfirmed}'),
47 ); 47 );
48 }), 48 }),
49 ), 49 ),
@@ -25,7 +25,7 @@ class DetailsView extends StatelessWidget { @@ -25,7 +25,7 @@ class DetailsView extends StatelessWidget {
25 child: Scaffold( 25 child: Scaffold(
26 backgroundColor: Colors.transparent, 26 backgroundColor: Colors.transparent,
27 appBar: AppBar( 27 appBar: AppBar(
28 - title: Text("Details"), 28 + title: Text('details'.tr),
29 backgroundColor: Colors.black12, 29 backgroundColor: Colors.black12,
30 elevation: 0, 30 elevation: 0,
31 centerTitle: true, 31 centerTitle: true,
@@ -42,7 +42,7 @@ class DetailsView extends StatelessWidget { @@ -42,7 +42,7 @@ class DetailsView extends StatelessWidget {
42 height: 35, 42 height: 35,
43 ), 43 ),
44 Text( 44 Text(
45 - "Total Confirmed", 45 + 'total_confirmed'.tr,
46 style: TextStyle( 46 style: TextStyle(
47 fontSize: 25, 47 fontSize: 25,
48 ), 48 ),
@@ -55,7 +55,7 @@ class DetailsView extends StatelessWidget { @@ -55,7 +55,7 @@ class DetailsView extends StatelessWidget {
55 height: 10, 55 height: 10,
56 ), 56 ),
57 Text( 57 Text(
58 - "Total Deaths", 58 + 'total_deaths'.tr,
59 style: TextStyle( 59 style: TextStyle(
60 fontSize: 25, 60 fontSize: 25,
61 ), 61 ),
@@ -68,7 +68,7 @@ class DetailsView extends StatelessWidget { @@ -68,7 +68,7 @@ class DetailsView extends StatelessWidget {
68 height: 10, 68 height: 10,
69 ), 69 ),
70 Text( 70 Text(
71 - "Total Recovered", 71 + 'total_recovered'.tr,
72 style: TextStyle( 72 style: TextStyle(
73 fontSize: 25, 73 fontSize: 25,
74 ), 74 ),
@@ -21,7 +21,7 @@ class HomeView extends GetView<HomeController> { @@ -21,7 +21,7 @@ class HomeView extends GetView<HomeController> {
21 child: Scaffold( 21 child: Scaffold(
22 backgroundColor: Colors.transparent, 22 backgroundColor: Colors.transparent,
23 appBar: AppBar( 23 appBar: AppBar(
24 - title: Text("Corona Virus"), 24 + title: Text('covid'.tr),
25 backgroundColor: Colors.white10, 25 backgroundColor: Colors.white10,
26 elevation: 0, 26 elevation: 0,
27 centerTitle: true, 27 centerTitle: true,
@@ -36,7 +36,7 @@ class HomeView extends GetView<HomeController> { @@ -36,7 +36,7 @@ class HomeView extends GetView<HomeController> {
36 height: 100, 36 height: 100,
37 ), 37 ),
38 Text( 38 Text(
39 - "Total Confirmed", 39 + 'total_confirmed'.tr,
40 style: TextStyle( 40 style: TextStyle(
41 fontSize: 30, 41 fontSize: 30,
42 ), 42 ),
@@ -49,7 +49,7 @@ class HomeView extends GetView<HomeController> { @@ -49,7 +49,7 @@ class HomeView extends GetView<HomeController> {
49 height: 10, 49 height: 10,
50 ), 50 ),
51 Text( 51 Text(
52 - "Total Deaths", 52 + 'total_deaths'.tr,
53 style: TextStyle( 53 style: TextStyle(
54 fontSize: 30, 54 fontSize: 30,
55 ), 55 ),
@@ -71,7 +71,7 @@ class HomeView extends GetView<HomeController> { @@ -71,7 +71,7 @@ class HomeView extends GetView<HomeController> {
71 Get.toNamed('/home/country'); 71 Get.toNamed('/home/country');
72 }, 72 },
73 child: Text( 73 child: Text(
74 - "Fetch by country", 74 + 'fetch_country'.tr,
75 style: TextStyle(fontWeight: FontWeight.bold), 75 style: TextStyle(fontWeight: FontWeight.bold),
76 ), 76 ),
77 ) 77 )
  1 +// This is a basic Flutter widget test.
  2 +//
  3 +// To perform an interaction with a widget in your test, use the WidgetTester
  4 +// utility that Flutter provides. For example, you can send tap and scroll
  5 +// gestures. You can also use WidgetTester to find child widgets in the widget
  6 +// tree, read text, and verify that the values of widget properties are correct.
  7 +
  8 +import 'package:flutter/material.dart';
  9 +import 'package:flutter_test/flutter_test.dart';
  10 +
  11 +import '../lib/main.dart';
  12 +
  13 +void main() {
  14 + testWidgets('Counter increments smoke test', (WidgetTester tester) async {
  15 + // Build our app and trigger a frame.
  16 + await tester.pumpWidget(MyApp());
  17 +
  18 + // Verify that our counter starts at 0.
  19 + expect(find.text('0'), findsOneWidget);
  20 + expect(find.text('1'), findsNothing);
  21 +
  22 + // Tap the '+' icon and trigger a frame.
  23 + await tester.tap(find.byIcon(Icons.add));
  24 + await tester.pump();
  25 +
  26 + // Verify that our counter has incremented.
  27 + expect(find.text('0'), findsNothing);
  28 + expect(find.text('1'), findsOneWidget);
  29 + });
  30 +}
@@ -388,9 +388,9 @@ class GetInstance { @@ -388,9 +388,9 @@ class GetInstance {
388 return false; 388 return false;
389 } 389 }
390 390
391 - if (i is GetLifeCycle) { 391 + if (i is GetLifeCycleBase && i.onDelete != null) {
392 i.onDelete(); 392 i.onDelete();
393 - Get.log('"$newKey" onClose() called'); 393 + Get.log('"$newKey" onDelete() called');
394 } 394 }
395 395
396 _singl.remove(newKey); 396 _singl.remove(newKey);
@@ -111,7 +111,7 @@ class GetMaterialApp extends StatelessWidget { @@ -111,7 +111,7 @@ class GetMaterialApp extends StatelessWidget {
111 final ThemeData highContrastDarkTheme; 111 final ThemeData highContrastDarkTheme;
112 final Map<Type, Action<Intent>> actions; 112 final Map<Type, Action<Intent>> actions;
113 final bool debugShowMaterialGrid; 113 final bool debugShowMaterialGrid;
114 - final Function(Routing) routingCallback; 114 + final ValueChanged<Routing> routingCallback;
115 final Transition defaultTransition; 115 final Transition defaultTransition;
116 final bool opaqueRoute; 116 final bool opaqueRoute;
117 final VoidCallback onInit; 117 final VoidCallback onInit;
@@ -50,6 +50,7 @@ class SnackRoute<T> extends OverlayRoute<T> { @@ -50,6 +50,7 @@ class SnackRoute<T> extends OverlayRoute<T> {
50 Alignment _initialAlignment; 50 Alignment _initialAlignment;
51 Alignment _endAlignment; 51 Alignment _endAlignment;
52 bool _wasDismissedBySwipe = false; 52 bool _wasDismissedBySwipe = false;
  53 + bool _onTappedDismiss = false;
53 54
54 Timer _timer; 55 Timer _timer;
55 56
@@ -62,7 +63,12 @@ class SnackRoute<T> extends OverlayRoute<T> { @@ -62,7 +63,12 @@ class SnackRoute<T> extends OverlayRoute<T> {
62 OverlayEntry( 63 OverlayEntry(
63 builder: (context) { 64 builder: (context) {
64 return GestureDetector( 65 return GestureDetector(
65 - onTap: snack.isDismissible ? Get.back : null, 66 + onTap: () {
  67 + if (snack.isDismissible && !_onTappedDismiss) {
  68 + _onTappedDismiss = true;
  69 + Get.back();
  70 + }
  71 + },
66 child: AnimatedBuilder( 72 child: AnimatedBuilder(
67 animation: _filterBlurAnimation, 73 animation: _filterBlurAnimation,
68 builder: (context, child) { 74 builder: (context, child) {
@@ -132,7 +132,7 @@ extension StateExt<T> on StateMixin<T> { @@ -132,7 +132,7 @@ extension StateExt<T> on StateMixin<T> {
132 assert(widget != null); 132 assert(widget != null);
133 return SimpleBuilder(builder: (_) { 133 return SimpleBuilder(builder: (_) {
134 if (status.isLoading) { 134 if (status.isLoading) {
135 - return onLoading ?? Center(child: CircularProgressIndicator()); 135 + return onLoading ?? const Center(child: CircularProgressIndicator());
136 } else if (status.isError) { 136 } else if (status.isError) {
137 return onError != null 137 return onError != null
138 ? onError(status.errorMessage) 138 ? onError(status.errorMessage)
@@ -518,17 +518,16 @@ class GetUtils { @@ -518,17 +518,16 @@ class GetUtils {
518 /// Capitalize each word inside string 518 /// Capitalize each word inside string
519 /// Example: your name => Your Name, your name => Your name 519 /// Example: your name => Your Name, your name => Your name
520 static String capitalize(String value) { 520 static String capitalize(String value) {
521 - if (isNullOrBlank(value)) return null; 521 + if (isNull(value)) return null;
  522 + if (isBlank(value)) return value;
522 return value.split(' ').map(capitalizeFirst).join(' '); 523 return value.split(' ').map(capitalizeFirst).join(' ');
523 } 524 }
524 525
525 /// Uppercase first letter inside string and let the others lowercase 526 /// Uppercase first letter inside string and let the others lowercase
526 /// Example: your name => Your name 527 /// Example: your name => Your name
527 static String capitalizeFirst(String s) { 528 static String capitalizeFirst(String s) {
528 - if (isNullOrBlank(s)) {  
529 - return null;  
530 - }  
531 - 529 + if (isNull(s)) return null;
  530 + if (isBlank(s)) return s;
532 return s[0].toUpperCase() + s.substring(1).toLowerCase(); 531 return s[0].toUpperCase() + s.substring(1).toLowerCase();
533 } 532 }
534 533
@@ -15,7 +15,8 @@ void main() { @@ -15,7 +15,8 @@ void main() {
15 ListTile( 15 ListTile(
16 leading: Icon(Icons.music_note), 16 leading: Icon(Icons.music_note),
17 title: Text('Music'), 17 title: Text('Music'),
18 - onTap: () => {}), 18 + onTap: () {},
  19 + ),
19 ], 20 ],
20 ), 21 ),
21 )); 22 ));
@@ -36,7 +37,8 @@ void main() { @@ -36,7 +37,8 @@ void main() {
36 ListTile( 37 ListTile(
37 leading: Icon(Icons.music_note), 38 leading: Icon(Icons.music_note),
38 title: Text('Music'), 39 title: Text('Music'),
39 - onTap: () => {}), 40 + onTap: () {},
  41 + ),
40 ], 42 ],
41 ), 43 ),
42 )); 44 ));
@@ -679,14 +679,17 @@ void main() { @@ -679,14 +679,17 @@ void main() {
679 expect('foo bar'.capitalize, 'Foo Bar'); 679 expect('foo bar'.capitalize, 'Foo Bar');
680 expect('FoO bAr'.capitalize, 'Foo Bar'); 680 expect('FoO bAr'.capitalize, 'Foo Bar');
681 expect('FOO BAR'.capitalize, 'Foo Bar'); 681 expect('FOO BAR'.capitalize, 'Foo Bar');
682 - expect(''.capitalize, null); 682 + expect(null.capitalize, null);
  683 + expect(''.capitalize, '');
  684 + expect('foo bar '.capitalize, 'Foo Bar ');
683 }); 685 });
684 686
685 test('var.capitalizeFirst', () { 687 test('var.capitalizeFirst', () {
686 expect('foo bar'.capitalizeFirst, 'Foo bar'); 688 expect('foo bar'.capitalizeFirst, 'Foo bar');
687 expect('FoO bAr'.capitalizeFirst, 'Foo bar'); 689 expect('FoO bAr'.capitalizeFirst, 'Foo bar');
688 expect('FOO BAR'.capitalizeFirst, 'Foo bar'); 690 expect('FOO BAR'.capitalizeFirst, 'Foo bar');
689 - expect(''.capitalizeFirst, null); 691 + expect(null.capitalizeFirst, null);
  692 + expect(''.capitalizeFirst, '');
690 }); 693 });
691 694
692 test('var.removeAllWhitespace', () { 695 test('var.removeAllWhitespace', () {