Showing
3 changed files
with
115 additions
and
21 deletions
1 | +## [2.5.8] | ||
2 | +- Added docs | ||
3 | + | ||
4 | +## [2.5.7] | ||
5 | +- Fix Get.generalDialog optionals | ||
6 | +- Added GetX onInit support | ||
7 | + | ||
8 | +## [2.5.6] | ||
9 | +- GetBuilder refactor to work with lazyPut. | ||
10 | +Now you can list your controllers in advance with Get.lazyPut, and only when it is called for the first time will it be relocated in memory. | ||
11 | + | ||
12 | +## [2.5.5] | ||
13 | +- Fix arguments broken by new methods | ||
14 | + | ||
15 | +## [2.5.4] | ||
16 | +- Refactor methods | ||
17 | + | ||
18 | +## [2.5.3] | ||
19 | +- Fix snackbar padding on iPhone SE 2. | ||
20 | +- Added themes docs | ||
21 | + | ||
1 | ## [2.5.2] | 22 | ## [2.5.2] |
2 | - Fix: key not found when Get.key is used with no MaterialApp | 23 | - Fix: key not found when Get.key is used with no MaterialApp |
3 | 24 |
@@ -40,6 +40,16 @@ This library that will change the way you work with the Framework and save your | @@ -40,6 +40,16 @@ This library that will change the way you work with the Framework and save your | ||
40 | - **[Other Advanced APIs and Manual configurations](#Other-Advanced-APIs-and-Manual-configurations)** | 40 | - **[Other Advanced APIs and Manual configurations](#Other-Advanced-APIs-and-Manual-configurations)** |
41 | - **[Nested Navigators](#Nested-Navigators)** | 41 | - **[Nested Navigators](#Nested-Navigators)** |
42 | 42 | ||
43 | + | ||
44 | +#### You can contribute to the project in multiple ways: | ||
45 | +- Helping to translate the readme into other languages. | ||
46 | +- Adding documentation to the readme (not even half of Get's functions have been documented yet). | ||
47 | +- Writing articles/videos about Get (they will be inserted in the Readme, and in the future in our Wiki). | ||
48 | +- Offering PRs for code/tests. | ||
49 | +- Including new functions. | ||
50 | + | ||
51 | +Any contribution is welcome! | ||
52 | + | ||
43 | ## How to use? | 53 | ## How to use? |
44 | 54 | ||
45 | <!-- - Flutter Master/Dev/Beta: version 2.0.x-dev | 55 | <!-- - Flutter Master/Dev/Beta: version 2.0.x-dev |
@@ -88,13 +98,13 @@ var data = await Get.to(Payment()); | @@ -88,13 +98,13 @@ var data = await Get.to(Payment()); | ||
88 | on other screen, send a data for previous route: | 98 | on other screen, send a data for previous route: |
89 | 99 | ||
90 | ```dart | 100 | ```dart |
91 | -Get.back(result: 'success'); | 101 | +Get.back(result: 'sucess'); |
92 | ``` | 102 | ``` |
93 | And use it: | 103 | And use it: |
94 | 104 | ||
95 | ex: | 105 | ex: |
96 | ```dart | 106 | ```dart |
97 | -if(data == 'success') madeAnything(); | 107 | +if(data == 'sucess') madeAnything(); |
98 | ``` | 108 | ``` |
99 | 109 | ||
100 | Don't you want to learn our syntax? | 110 | Don't you want to learn our syntax? |
@@ -348,9 +358,12 @@ FloatingActionButton( | @@ -348,9 +358,12 @@ FloatingActionButton( | ||
348 | When you press FloatingActionButton, all widgets that are listening to the 'counter' variable will be updated automatically. | 358 | When you press FloatingActionButton, all widgets that are listening to the 'counter' variable will be updated automatically. |
349 | 359 | ||
350 | #### No StatefulWidget: | 360 | #### No StatefulWidget: |
351 | -Using StatefulWidgets means storing the state of entire screens unnecessarily. With Get the use of StatefulWidget is optional. Avoid them and save your users' RAM. | 361 | +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, which will be another StatefulWidget. |
362 | +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! | ||
363 | +Unless you need to use a mixin, like TickerProviderStateMixin, it will be totally unnecessary to use a StatefulWidget with Get. | ||
352 | 364 | ||
353 | -If you need to call initState() or dispose() method, you can call them directly from GetBuilder(); | 365 | +You can call all methods of a StatefulWidget directly from a GetBuilder. |
366 | +If you need to call initState() or dispose() method for example, you can call them directly; | ||
354 | 367 | ||
355 | ```dart | 368 | ```dart |
356 | GetBuilder<Controller>( | 369 | GetBuilder<Controller>( |
@@ -360,8 +373,22 @@ GetBuilder<Controller>( | @@ -360,8 +373,22 @@ GetBuilder<Controller>( | ||
360 | ), | 373 | ), |
361 | ``` | 374 | ``` |
362 | 375 | ||
376 | +A much better approach than this is to use the onInit() and onClose() method directly from your controller. | ||
377 | + | ||
378 | +```dart | ||
379 | +@override | ||
380 | +void onInit() { | ||
381 | + fetchApi(); | ||
382 | + super.onInit(); | ||
383 | +} | ||
384 | +``` | ||
385 | + | ||
386 | +- 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. | ||
387 | +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. | ||
363 | 388 | ||
364 | -- NOTE: If you are working with reactive programming with Get, know that it automatically closes your streams, as long as you close them correctly inside the close() method; | 389 | +So to simplify this: |
390 | +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. | ||
391 | +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. | ||
365 | 392 | ||
366 | Do not call a dispose method inside GetController, 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: | 393 | Do not call a dispose method inside GetController, 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: |
367 | 394 | ||
@@ -370,15 +397,19 @@ class Controller extends GetController { | @@ -370,15 +397,19 @@ class Controller extends GetController { | ||
370 | StreamController<User> user = StreamController<User>(); | 397 | StreamController<User> user = StreamController<User>(); |
371 | StreamController<String> name = StreamController<String>(); | 398 | StreamController<String> name = StreamController<String>(); |
372 | 399 | ||
373 | -/// close stream = close method, not dispose. | 400 | +/// close stream = onClose method, not dispose. |
374 | @override | 401 | @override |
375 | -void close() { | 402 | +void onClose() { |
376 | user.close(); | 403 | user.close(); |
377 | name.close(); | 404 | name.close(); |
378 | - super.close(); | 405 | + super.onClose(); |
379 | } | 406 | } |
380 | 407 | ||
381 | ``` | 408 | ``` |
409 | +Controller life cycle: | ||
410 | +- onInit() where it is created. | ||
411 | +- onClose() where it is closed to make any changes in preparation for the delete method | ||
412 | +- 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. | ||
382 | 413 | ||
383 | ##### Forms of use: | 414 | ##### Forms of use: |
384 | 415 | ||
@@ -420,7 +451,7 @@ GetBuilder<Controller>( | @@ -420,7 +451,7 @@ GetBuilder<Controller>( | ||
420 | )), | 451 | )), |
421 | ``` | 452 | ``` |
422 | 453 | ||
423 | -- Not recommended (because you will need to use StatefulWidget to instantiate your controller), but functional: | 454 | +- 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: |
424 | 455 | ||
425 | ```dart | 456 | ```dart |
426 | 457 | ||
@@ -433,8 +464,9 @@ GetBuilder( // you dont need to type on this way | @@ -433,8 +464,9 @@ GetBuilder( // you dont need to type on this way | ||
433 | )), | 464 | )), |
434 | 465 | ||
435 | ``` | 466 | ``` |
467 | +This approach is not recommended, as you will have to manually dispose of your controllers, close your streams manually, and literally give up one of the great benefits of this library, which is intelligent memory control. But if you trust your potential, go ahead! | ||
436 | 468 | ||
437 | -If you want to refine a widget's update control, you can assign them unique IDs: | 469 | +If you want to refine a widget's update control with GetBuilder, you can assign them unique IDs: |
438 | ```dart | 470 | ```dart |
439 | GetBuilder<Controller>( | 471 | GetBuilder<Controller>( |
440 | id: 'text' | 472 | id: 'text' |
@@ -443,14 +475,23 @@ GetBuilder<Controller>( | @@ -443,14 +475,23 @@ GetBuilder<Controller>( | ||
443 | '${Get.find<Controller>().counter}', //here | 475 | '${Get.find<Controller>().counter}', //here |
444 | )), | 476 | )), |
445 | ``` | 477 | ``` |
446 | -And update it fis form: | 478 | +And update it this form: |
447 | ```dart | 479 | ```dart |
448 | update(this,['text']); | 480 | update(this,['text']); |
449 | - | 481 | +``` |
450 | You can also impose conditions for the update: | 482 | You can also impose conditions for the update: |
451 | 483 | ||
452 | -``` | 484 | +```dart |
453 | update(this,['text'], counter < 10); | 485 | update(this,['text'], counter < 10); |
486 | +``` | ||
487 | + | ||
488 | +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). | ||
489 | +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. However, there are situations where you want only the widget where a certain variable has been changed to be rebuilt, and this is what GetX does with a mastery never seen before. | ||
490 | + | ||
491 | +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. | ||
492 | + | ||
493 | +You can use both in any situation, but if you want to tune their application to the maximum possible performance, I would say that: if your variables are changed at different times, use GetX, because there is no competition for it when the subject is to rebuild only what is necessary, if you do not need unique IDs, because all your variables will be changed when you perform an action, use GetBuilder, because it is a simple state updater in blocks, made in a few lines of code, to make just what he promises to do: update state in blocks. There is no way to compare RAM, CPU, or anything else from a giant state manager to a simple StatefulWidget (like GetBuilder) that is updated when you call update(this). It was done in a simple way, to have the least computational logic involved, just to fulfill a single purpose and spend the minimum resources possible for that purpose. | ||
494 | +If you want a powerful state manager, you can go without fear to GetX. It does not work with variables, but flows, everything in it is streams under the hood. You can use rxDart in conjunction with it, because everything is stream, you can hear the event of each "variable", because everything in it is stream, it is literally BLoC, easier than MobX, and without code generator or decorations . | ||
454 | 495 | ||
455 | 496 | ||
456 | ## Reactive State Manager | 497 | ## Reactive State Manager |
@@ -507,7 +548,7 @@ Do you know Flutter's counter app? Your Controller class might look like this: | @@ -507,7 +548,7 @@ Do you know Flutter's counter app? Your Controller class might look like this: | ||
507 | 548 | ||
508 | ```dart | 549 | ```dart |
509 | class CountCtl extends RxController { | 550 | class CountCtl extends RxController { |
510 | - int count = 0.obs; | 551 | + final count = 0.obs; |
511 | } | 552 | } |
512 | ``` | 553 | ``` |
513 | With a simple: | 554 | With a simple: |
@@ -556,6 +597,32 @@ Camila | @@ -556,6 +597,32 @@ Camila | ||
556 | 597 | ||
557 | ``` | 598 | ``` |
558 | 599 | ||
600 | +Before you immerse yourself in this world, I will give you a tip, always access the "value" of your flow when reading it, especially if you are working with lists where this is apparently optional. | ||
601 | +You can access list.length, or list.value.length. Most of the time, both ways will work, since the GetX list inherits directly from the dart List. But there is a difference between you accessing the object, and accessing the flow. I strongly recommend you to access the value: | ||
602 | +```dart | ||
603 | +final list = List<User>().obs; | ||
604 | +``` | ||
605 | +```dart | ||
606 | +ListView.builder ( | ||
607 | +itemCount: list.value.lenght | ||
608 | +``` | ||
609 | +or else create a "get" method for it and abandon "value" for life. example: | ||
610 | + | ||
611 | +```dart | ||
612 | +final _list = List<User>().obs; | ||
613 | +List get list => _list.value; | ||
614 | +``` | ||
615 | +```dart | ||
616 | +ListView.builder ( | ||
617 | +itemCount: list.lenght | ||
618 | +``` | ||
619 | +You could add an existing list of another type to the observable list using a list.assign (oldList); or the assignAll method, which differs from add, and addAll, which must be of the same type. All existing methods in a list are also available on GetX. | ||
620 | + | ||
621 | +We could remove the obligation to use value with a simple decoration and code generator, but the purpose of this lib is precisely not to need any external dependency. It is to offer an environment ready for programming, involving the essentials (management of routes, dependencies and states), in a simple, light and performance way without needing any external package. You can literally add 3 letters to your pubspec (get) and start programming. All solutions included by default, from route management to state management, aim at ease, productivity and performance. 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. 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. | ||
622 | +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. | ||
623 | + | ||
624 | +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. | ||
625 | + | ||
559 | ## Simple Instance Manager | 626 | ## Simple Instance Manager |
560 | Are you already using Get and want to make your project as lean as possible? 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: | 627 | Are you already using Get and want to make your project as lean as possible? 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: |
561 | 628 | ||
@@ -638,7 +705,7 @@ print(Get.arguments); | @@ -638,7 +705,7 @@ print(Get.arguments); | ||
638 | ``` | 705 | ``` |
639 | 706 | ||
640 | #### Dynamic urls links | 707 | #### Dynamic urls links |
641 | -Get is the first and only package to offer advanced dynamic urls just like on the Web. Web developers have probably already wanted this feature on Flutter, and most likely have seen a package promise this feature and deliver a totally different syntax than a URL would have on web, but Get also solves that. | 708 | +Get offer advanced dynamic urls just like on the Web. Web developers have probably already wanted this feature on Flutter, and most likely have seen a package promise this feature and deliver a totally different syntax than a URL would have on web, but Get also solves that. |
642 | 709 | ||
643 | ```dart | 710 | ```dart |
644 | Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo"); | 711 | Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo"); |
@@ -802,21 +869,27 @@ class Third extends StatelessWidget { | @@ -802,21 +869,27 @@ class Third extends StatelessWidget { | ||
802 | 869 | ||
803 | ### Change Theme | 870 | ### Change Theme |
804 | Please do not use any higher level widget than GetMaterialApp in order to update it. This can trigger duplicate keys. A lot of people are used to the prehistoric approach of creating a "ThemeProvider" widget just to change the theme of your app, and this is definitely NOT necessary with Get. | 871 | Please do not use any higher level widget than GetMaterialApp in order to update it. This can trigger duplicate keys. A lot of people are used to the prehistoric approach of creating a "ThemeProvider" widget just to change the theme of your app, and this is definitely NOT necessary with Get. |
805 | -If you want to change the theme, just use: | 872 | + |
873 | +You can create your custom theme and simply add it within Get.changeTheme without any boilerplate for that: | ||
874 | + | ||
806 | 875 | ||
807 | ```dart | 876 | ```dart |
808 | -Get.changeTheme (Theme.dark()); | 877 | +Get.changeTheme(ThemeData.light()); |
809 | ``` | 878 | ``` |
810 | 879 | ||
811 | -If you want to create something like a button that changes the theme with touch, you can combine two Get APIs for that, the api that checks if the dark theme is being used, and the theme change API, you can just put this within an onPressed: | 880 | +If you want to create something like a button that changes the theme with onTap, you can combine two Get APIs for that, the api that checks if the dark theme is being used, and the theme change API, you can just put this within an onPressed: |
812 | 881 | ||
813 | ```dart | 882 | ```dart |
814 | -Get.changeTheme (Get.isDarkMode? Theme.light(): Theme.dark()); | 883 | +Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark()); |
815 | ``` | 884 | ``` |
816 | 885 | ||
817 | When darkmode is activated, it will switch to the light theme, and when the light theme is activated, it will change to dark. | 886 | When darkmode is activated, it will switch to the light theme, and when the light theme is activated, it will change to dark. |
818 | 887 | ||
819 | -You can create your custom theme and simply add it within Get.changeTheme without any cliche code for that. | 888 | + |
889 | +If you want to know in depth how to change the theme, you can follow this tutorial on Medium that even teaches the persistence of the theme using Get: | ||
890 | + | ||
891 | +- [Dynamic Themes in 3 lines using Get](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Tutorial by [Rod Brown](https://github.com/RodBr). | ||
892 | + | ||
820 | 893 | ||
821 | ### Optional Global Settings | 894 | ### Optional Global Settings |
822 | You can create Global settings for Get. Just add Get.config to your code before pushing any route or do it directly in your GetMaterialApp | 895 | You can create Global settings for Get. Just add Get.config to your code before pushing any route or do it directly in your GetMaterialApp |
1 | name: get | 1 | name: get |
2 | description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get. | 2 | description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get. |
3 | -version: 2.5.5 | 3 | +version: 2.5.8 |
4 | homepage: https://github.com/jonataslaw/get | 4 | homepage: https://github.com/jonataslaw/get |
5 | 5 | ||
6 | environment: | 6 | environment: |
-
Please register or login to post a comment