Nipodemos

BindingBuilder added in english docs

  1 +# Dependency management
1 - [Simple Instance Manager](#simple-instance-manager) 2 - [Simple Instance Manager](#simple-instance-manager)
2 - [Options](#options) 3 - [Options](#options)
3 - [Bindings](#bindings) 4 - [Bindings](#bindings)
4 - [How to use](#how-to-use) 5 - [How to use](#how-to-use)
5 - [SmartManagement](#smartmanagement) 6 - [SmartManagement](#smartmanagement)
6 7
7 -## Simple Instance Manager  
8 -  
9 Get has a simple and powerful dependency manager that allows you to retrieve the same class as your Bloc or Controller with just 1 lines of code, no Provider context, no inheritedWidget: 8 Get has a simple and powerful dependency manager that allows you to retrieve the same class as your Bloc or Controller with just 1 lines of code, no Provider context, no inheritedWidget:
10 9
11 ```dart 10 ```dart
12 Controller controller = Get.put(Controller()); // Rather Controller controller = Controller(); 11 Controller controller = Get.put(Controller()); // Rather Controller controller = Controller();
13 ``` 12 ```
14 13
15 -- Note: If you are using Get's State Manager, pay more attention to the bindings api, which will make easier to connect your view to your controller. 14 +If you don't know why dependency injection is, you can check some links to learn:
  15 +[Dependency Injection in Flutter](https://medium.com/flutter-community/dependency-injection-in-flutter-f19fb66a0740)
  16 +[Dependency Injection in Dart/Flutter Apps](https://berthacks.com/dependency-injection-in-dartflutter-apps-ck71x93uu06fqd9s1zuosczgn)
16 17
17 Instead of instantiating your class within the class you are using, you are instantiating it within the Get instance, which will make it available throughout your App. 18 Instead of instantiating your class within the class you are using, you are instantiating it within the Get instance, which will make it available throughout your App.
18 So you can use your controller (or Bloc class) normally 19 So you can use your controller (or Bloc class) normally
19 20
20 -**Tip:** Get dependency management is decloupled from other parts of the package, so if for example your app is already using a state manager (any one, it doesn't matter), you don't need to rewrite it all, you can use this dependency injection with no problems at all  
21 -  
22 -```dart  
23 -controller.fetchApi();  
24 -```  
25 -  
26 Imagine that you have navigated through numerous routes, and you need a data that was left behind in your controller, you would need a state manager combined with the Provider or Get_it, correct? Not with Get. You just need to ask Get to "find" for your controller, you don't need any additional dependencies: 21 Imagine that you have navigated through numerous routes, and you need a data that was left behind in your controller, you would need a state manager combined with the Provider or Get_it, correct? Not with Get. You just need to ask Get to "find" for your controller, you don't need any additional dependencies:
27 22
28 ```dart 23 ```dart
@@ -36,24 +31,27 @@ And then you will be able to recover your controller data that was obtained back @@ -36,24 +31,27 @@ And then you will be able to recover your controller data that was obtained back
36 Text(controller.textFromApi); 31 Text(controller.textFromApi);
37 ``` 32 ```
38 33
39 -Looking for lazy loading? You can declare all your controllers, and it will be called only when someone needs it. You can do this with: 34 +It is possible to lazyLoad a dependency so that it will be instantiated only when is used. Very useful for computational expensive classes or when you know you will not gonna use that class at that time.
40 35
41 ```dart 36 ```dart
42 -Get.lazyPut<Service>(()=> ApiMock());  
43 -/// ApiMock will only be called when someone uses Get.find<Service> for the first time 37 +Get.lazyPut<ApiMock>(()=> ApiMock());
  38 +/// ApiMock will only be called when someone uses Get.find<ApiMock> for the first time
44 ``` 39 ```
45 40
46 -If you want to register an asynchronous instance, you can use Get.putAsync. 41 +If you want to register an asynchronous instance, you can use `Get.putAsync`:
47 42
48 ```dart 43 ```dart
49 Get.putAsync<SharedPreferences>(() async { 44 Get.putAsync<SharedPreferences>(() async {
50 - final prefs = await SharedPreferences.getInstance();  
51 - await prefs.setInt('counter', 12345);  
52 - return prefs; 45 + final prefs = await SharedPreferences.getInstance();
  46 + await prefs.setInt('counter', 12345);
  47 + return prefs;
53 }); 48 });
54 ``` 49 ```
55 50
56 -usage: 51 +- Note: If you are using Get's State Manager, pay more attention to the [Bindings](#bindings) api, which will make easier to connect your view to your controller.
  52 +- Note²: Get dependency management is decloupled from other parts of the package, so if for example your app is already using a state manager (any one, it doesn't matter), you don't need to change that, you can use this dependency injection manager with no problems at all
  53 +
  54 +## Usage
57 55
58 ```dart 56 ```dart
59 int count = Get.find<SharedPreferences>().getInt('counter'); 57 int count = Get.find<SharedPreferences>().getInt('counter');
@@ -70,12 +68,12 @@ Get.delete<Controller>(); @@ -70,12 +68,12 @@ Get.delete<Controller>();
70 68
71 Although Getx already delivers very good settings for use, it is possible to refine them even more so that it become more useful to the programmer. The methods and it's configurable parameters are: 69 Although Getx already delivers very good settings for use, it is possible to refine them even more so that it become more useful to the programmer. The methods and it's configurable parameters are:
72 70
73 -- Get.put(): 71 +### Get.put()
74 72
75 ```dart 73 ```dart
76 Get.put<S>( 74 Get.put<S>(
77 // mandatory: the class that you want to get to save, like a controller or anything 75 // mandatory: the class that you want to get to save, like a controller or anything
78 - // note: that "S" means that it can be anything 76 + // note: "S" means that it can be a class of any type
79 S dependency 77 S dependency
80 78
81 // optional: this is for when you want multiple classess that are of the same type 79 // optional: this is for when you want multiple classess that are of the same type
@@ -96,11 +94,16 @@ Get.put<S>( @@ -96,11 +94,16 @@ Get.put<S>(
96 bool overrideAbstract = false, 94 bool overrideAbstract = false,
97 95
98 // optional: allows you to create the dependency using function instead of the dependency itself. 96 // optional: allows you to create the dependency using function instead of the dependency itself.
  97 + // this one is not commonly used
99 InstanceBuilderCallback<S> builder, 98 InstanceBuilderCallback<S> builder,
100 ) 99 )
  100 +
  101 +// Example:
  102 +
  103 +Get.put<LoginController>(LoginController(), permanent: true)
101 ``` 104 ```
102 105
103 -- Get.lazyPut: 106 +### Get.lazyPut
104 107
105 ```dart 108 ```dart
106 Get.lazyPut<S>( 109 Get.lazyPut<S>(
@@ -119,9 +122,19 @@ Get.lazyPut<S>( @@ -119,9 +122,19 @@ Get.lazyPut<S>(
119 bool fenix = false 122 bool fenix = false
120 123
121 ) 124 )
  125 +
  126 +// example
  127 +Get.lazyPut<FirebaseAuth>(
  128 + () => {
  129 + // ... some logic if needed
  130 + FirebaseAuth()
  131 + },
  132 + tag: Math.random().toString(),
  133 + fenix: true
  134 +)
122 ``` 135 ```
123 136
124 -- Get.putAsync: 137 +### Get.putAsync
125 138
126 ```dart 139 ```dart
127 Get.putAsync<S>( 140 Get.putAsync<S>(
@@ -139,7 +152,7 @@ Get.putAsync<S>( @@ -139,7 +152,7 @@ Get.putAsync<S>(
139 bool permanent = false 152 bool permanent = false
140 ``` 153 ```
141 154
142 -- Get.create: 155 +### Get.create
143 156
144 ```dart 157 ```dart
145 Get.create<S>( 158 Get.create<S>(
@@ -160,19 +173,19 @@ Get.create<S>( @@ -160,19 +173,19 @@ Get.create<S>(
160 bool permanent = true 173 bool permanent = true
161 ``` 174 ```
162 175
163 -### Diferences between methods: 176 +## Diferences between methods:
164 177
165 First, let's of the `fenix` of Get.lazyPut and the `permanent` of the other methods. 178 First, let's of the `fenix` of Get.lazyPut and the `permanent` of the other methods.
166 179
167 The fundamental difference between `permanent` and `fenix` is how you want to store your instances. 180 The fundamental difference between `permanent` and `fenix` is how you want to store your instances.
168 Reinforcing: by default, GetX deletes instances when they are not is use. 181 Reinforcing: by default, GetX deletes instances when they are not is use.
169 It means that: If screen 1 has controller 1 and screen 2 has controller 2 and you remove the first route from stack, (like if you use `Get.off()` or `Get.offName()`) the controller 1 lost it's use so it will be erased. 182 It means that: If screen 1 has controller 1 and screen 2 has controller 2 and you remove the first route from stack, (like if you use `Get.off()` or `Get.offName()`) the controller 1 lost it's use so it will be erased.
170 -But if you want to opt to `permanent:true`, then the controller will not be lost in this transition - which is very usefult for services that you want to keep alive thoughout the entire application.  
171 -`fenix` in the other hand is for services that you don't worry in losing between screen changes, but when you need that service, you expect that it is alive. So basically, it will dispose the unused controller/service/class, but when you need that, it will "recreate from the ashes" a new instance. 183 +But if you want to opt for using `permanent:true`, then the controller will not be lost in this transition - which is very useful for services that you want to keep alive throughout the entire application.
  184 +`fenix` in the other hand is for services that you don't worry in losing between screen changes, but when you need that service, you expect that it is alive. So basically, it will dispose the unused controller/service/class, but when you need it, it will "recreate from the ashes" a new instance.
172 185
173 -Proceeding with the differences between methods: 186 +Proceeding with the differences between methods:
174 187
175 -- Get.put and Get.putAsync follow the same creation order, with the difference that asyn opt for applying a asynchronous method: those two methods create and initialize the instance. That one is inserted directly in the memory, using the internal method `insert` with the parameters `permanent: false` and `isSingleton: true` (this isSingleton parameter only porpuse is to tell if it is to use the dependency on `dependency` or if it is to use the dependency on `FcBuilderFunc`). After that, `Get.find()` is called that immediately initialize the instances that are on memory. 188 +- Get.put and Get.putAsync follow the same creation order, with the difference that the second uses an asynchronous method: those two methods create and initialize the instance. That one is inserted directly in the memory, using the internal method `insert` with the parameters `permanent: false` and `isSingleton: true` (this isSingleton parameter only porpuse is to tell if it is to use the dependency on `dependency` or if it is to use the dependency on `FcBuilderFunc`). After that, `Get.find()` is called that immediately initialize the instances that are on memory.
176 189
177 - Get.create: As the name implies, it will "create" your dependency! Similar to `Get.put()`, it also call the internal method `insert` to instancing. But `permanent` became true and `isSingleton` became false (since we are "creating" our dependency, there is no way for it to be a singleton instace, that's why is false). And because it has `permanent: true`, we have by default the benefit of not losing it between screens! Also, `Get.find()` is not called immediately, it wait to be used in the screen to be called. It is created this way to make use of the parameter `permanent`, since then, worth noticing, `Get.create()` was made with the goal of create not shared instances, but don't get disposed, like for example a button in a listView, that you want a unique instance for that list - because of that, Get.create must be used together with GetWidget. 190 - Get.create: As the name implies, it will "create" your dependency! Similar to `Get.put()`, it also call the internal method `insert` to instancing. But `permanent` became true and `isSingleton` became false (since we are "creating" our dependency, there is no way for it to be a singleton instace, that's why is false). And because it has `permanent: true`, we have by default the benefit of not losing it between screens! Also, `Get.find()` is not called immediately, it wait to be used in the screen to be called. It is created this way to make use of the parameter `permanent`, since then, worth noticing, `Get.create()` was made with the goal of create not shared instances, but don't get disposed, like for example a button in a listView, that you want a unique instance for that list - because of that, Get.create must be used together with GetWidget.
178 191
@@ -201,11 +214,18 @@ class HomeBinding implements Bindings { @@ -201,11 +214,18 @@ class HomeBinding implements Bindings {
201 Your IDE will automatically ask you to override the "dependencies" method, and you just need to click on the lamp, override the method, and insert all the classes you are going to use on that route: 214 Your IDE will automatically ask you to override the "dependencies" method, and you just need to click on the lamp, override the method, and insert all the classes you are going to use on that route:
202 215
203 ```dart 216 ```dart
204 -class HomeBinding implements Bindings{ 217 +class HomeBinding implements Bindings {
205 @override 218 @override
206 void dependencies() { 219 void dependencies() {
207 Get.lazyPut<ControllerX>(() => ControllerX()); 220 Get.lazyPut<ControllerX>(() => ControllerX());
208 - Get.lazyPut<Service>(()=> Api()); 221 + Get.put<Service>(()=> Api());
  222 + }
  223 +}
  224 +
  225 +class DetailsBinding implements Bindings {
  226 + @override
  227 + void dependencies() {
  228 + Get.lazyPut<DetailsController>(() => DetailsController());
209 } 229 }
210 } 230 }
211 ``` 231 ```
@@ -215,15 +235,25 @@ Now you just need to inform your route, that you will use that binding to make t @@ -215,15 +235,25 @@ Now you just need to inform your route, that you will use that binding to make t
215 - Using named routes: 235 - Using named routes:
216 236
217 ```dart 237 ```dart
218 -namedRoutes: {  
219 - '/': GetRoute(Home(), binding: HomeBinding())  
220 -} 238 +getPages: [
  239 + GetPage(
  240 + name: '/',
  241 + page: () => HomeView(),
  242 + binding: HomeBinding(),
  243 + ),
  244 + GetPage(
  245 + name: '/details',
  246 + page: () => DetailsView(),
  247 + binding: DetailsBinding(),
  248 + ),
  249 +];
221 ``` 250 ```
222 251
223 - Using normal routes: 252 - Using normal routes:
224 253
225 ```dart 254 ```dart
226 Get.to(Home(), binding: HomeBinding()); 255 Get.to(Home(), binding: HomeBinding());
  256 +Get.to(DetailsView(), binding: DetailsBinding())
227 ``` 257 ```
228 258
229 There, you don't have to worry about memory management of your application anymore, Get will do it for you. 259 There, you don't have to worry about memory management of your application anymore, Get will do it for you.
@@ -237,6 +267,37 @@ GetMaterialApp( @@ -237,6 +267,37 @@ GetMaterialApp(
237 ); 267 );
238 ``` 268 ```
239 269
  270 +### BindingsBuilder
  271 +
  272 +The default way of creating a binding creating a class that implements Bindings.
  273 +But alternatively, you can use `BindingsBuilder` callback so that you can simply use a function to instantiate whatever you desire.
  274 +
  275 +Example:
  276 +
  277 +```dart
  278 +getPages: [
  279 + GetPage(
  280 + name: '/',
  281 + page: () => HomeView(),
  282 + binding: BindingsBuilder(() => {
  283 + Get.lazyPut<ControllerX>(() => ControllerX());
  284 + Get.put<Service>(()=> Api());
  285 + }),
  286 + ),
  287 + GetPage(
  288 + name: '/details',
  289 + page: () => DetailsView(),
  290 + binding: BindingsBuilder(() => {
  291 + Get.lazyPut<DetailsController>(() => DetailsController());
  292 + }),
  293 + ),
  294 +];
  295 +```
  296 +
  297 +That way you can avoid to create one Binding class for each route making this even simpler.
  298 +
  299 +Both ways of doing work perfectly fine and we want you to use what most suit your tastes.
  300 +
240 ## SmartManagement 301 ## SmartManagement
241 302
242 Always prefer to use standard SmartManagement (full), you do not need to configure anything for that, Get already gives it to you by default. It will surely eliminate all your disused controllers from memory, as its refined control removes the dependency, even if a failure occurs and a widget that uses it is not properly disposed. 303 Always prefer to use standard SmartManagement (full), you do not need to configure anything for that, Get already gives it to you by default. It will surely eliminate all your disused controllers from memory, as its refined control removes the dependency, even if a failure occurs and a widget that uses it is not properly disposed.