Jonny Borges
Committed by GitHub

Bump to new Get!

1 -## [2.7.1] 1 +## [2.10.0]
  2 +- Added SmartManagement, your application's memory is managed intelligently like never before!
  3 +- Added Obx, a widget that knows when to rebuild a child, without needing any type.
  4 +- Added MIxinBuilder - If you need to use GetBuilder in conjunction with GetX, use GetController with this widget, and the changes will occur either using update (this) or changing some reactive variable. Use only if necessary, for better RAM consumption, prefer widgets in that order:
  5 +Obx => GetX => GetBuilder => MixinBuilder.
  6 +Obx is the lightest of all, and MixinBuilder is a mix of the other 3, whenever possible, use the specific widget.
  7 +- Refactor: refactor StateManager of Get.
  8 +- Changed: full List API refactor, now value is no longer needed.
  9 +- Added Workers: You can hear changes to a variable and trigger custom callbacks.
  10 +- Added Bindings API docs.
  11 +
  12 +# [2.7.1]
2 - Improve list to set and get methods 13 - Improve list to set and get methods
3 14
4 ## [2.7.0] 15 ## [2.7.0]
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 <img alt="Awesome Flutter" src="https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square" /> 9 <img alt="Awesome Flutter" src="https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square" />
10 </a> 10 </a>
11 11
  12 +
12 Get is an extra-light and powerful library for Flutter that will give you superpowers and increase your productivity. Navigate without context, open dialogs, snackbars or bottomsheets from anywhere in your code, Manage states and inject dependencies in an easy and practical way! Get is secure, stable, up-to-date, and offers a huge range of APIs that are not present on default framework. 13 Get is an extra-light and powerful library for Flutter that will give you superpowers and increase your productivity. Navigate without context, open dialogs, snackbars or bottomsheets from anywhere in your code, Manage states and inject dependencies in an easy and practical way! Get is secure, stable, up-to-date, and offers a huge range of APIs that are not present on default framework.
13 14
14 ```dart 15 ```dart
@@ -25,13 +26,28 @@ Navigator.of(context).push( @@ -25,13 +26,28 @@ Navigator.of(context).push(
25 // Get syntax 26 // Get syntax
26 Get.to(Home()); 27 Get.to(Home());
27 ``` 28 ```
  29 +**Complete example of the Flutter counter app in just 11 lines with Get**
  30 +
  31 +```dart
  32 +void main() => runApp(GetMaterialApp(home: Home()));
  33 +
  34 +class Home extends StatelessWidget {
  35 + final count = 0.obs;
  36 + @override
  37 + Widget build(context) => Scaffold(
  38 + appBar: AppBar(title: Text("Get change you life")),
  39 + floatingActionButton:
  40 + FloatingActionButton(onPressed: () => count.value++),
  41 + body: Center(child: Obx(() => Text(count.string))),
  42 + );
  43 +}
  44 +
  45 +```
28 46
29 ## Getting Started 47 ## Getting Started
30 48
31 Flutter's conventional navigation has a lot of unnecessary boilerplate, requires context to navigate between screens, open dialogs, and use snackbars on framework is really boring. 49 Flutter's conventional navigation has a lot of unnecessary boilerplate, requires context to navigate between screens, open dialogs, and use snackbars on framework is really boring.
32 -In addition, when a route is pushed, the entire MaterialApp can be rebuilt causing freezes, this does not happen with Get.  
33 -This library that will change the way you work with the Framework and save your life from cliche code, increasing your productivity, and eliminating the rebuild bugs of your application.  
34 - 50 +This library that will change the way you work with the Framework and save your life from boilerplate, increasing your productivity, and provide you with everything that is most modern when it comes to managing states, routes and dependencies.
35 51
36 - **[How to use?](#how-to-use)** 52 - **[How to use?](#how-to-use)**
37 - **[Navigating without named routes](#Navigating-without-named-routes)** 53 - **[Navigating without named routes](#Navigating-without-named-routes)**
@@ -40,7 +56,8 @@ This library that will change the way you work with the Framework and save your @@ -40,7 +56,8 @@ This library that will change the way you work with the Framework and save your
40 - **[BottomSheets](#BottomSheets)** 56 - **[BottomSheets](#BottomSheets)**
41 - **[Simple State Manager](#Simple-State-Manager)** 57 - **[Simple State Manager](#Simple-State-Manager)**
42 - **[Reactive State Manager](#Reactive-State-Manager)** 58 - **[Reactive State Manager](#Reactive-State-Manager)**
43 -- **[Simple Instance Manager](#Simple-Instance-Manager)** 59 +- **[Bindings](#Bindings)**
  60 +- **[Workers](#Workers)**
44 - **[Navigate with named routes](#Navigate-with-named-routes)** 61 - **[Navigate with named routes](#Navigate-with-named-routes)**
45 - **[Send data to named Routes](#Send-data-to-named-Routes)** 62 - **[Send data to named Routes](#Send-data-to-named-Routes)**
46 - **[Dynamic urls links](#Dynamic-urls-links)** 63 - **[Dynamic urls links](#Dynamic-urls-links)**
@@ -53,7 +70,7 @@ This library that will change the way you work with the Framework and save your @@ -53,7 +70,7 @@ This library that will change the way you work with the Framework and save your
53 #### You can contribute to the project in multiple ways: 70 #### You can contribute to the project in multiple ways:
54 - Helping to translate the readme into other languages. 71 - Helping to translate the readme into other languages.
55 - Adding documentation to the readme (not even half of Get's functions have been documented yet). 72 - Adding documentation to the readme (not even half of Get's functions have been documented yet).
56 -- Writing articles/videos about Get (they will be inserted in the Readme, and in the future in our Wiki). 73 +- Write articles or make videos teaching how to use Get (they will be inserted in the Readme and in the future in our Wiki).
57 - Offering PRs for code/tests. 74 - Offering PRs for code/tests.
58 - Including new functions. 75 - Including new functions.
59 76
@@ -370,7 +387,7 @@ FloatingActionButton( @@ -370,7 +387,7 @@ FloatingActionButton(
370 When you press FloatingActionButton, all widgets that are listening to the 'counter' variable will be updated automatically. 387 When you press FloatingActionButton, all widgets that are listening to the 'counter' variable will be updated automatically.
371 388
372 #### No StatefulWidget: 389 #### No StatefulWidget:
373 -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. 390 +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.
374 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! 391 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!
375 Unless you need to use a mixin, like TickerProviderStateMixin, it will be totally unnecessary to use a StatefulWidget with Get. 392 Unless you need to use a mixin, like TickerProviderStateMixin, it will be totally unnecessary to use a StatefulWidget with Get.
376 393
@@ -425,8 +442,6 @@ Controller life cycle: @@ -425,8 +442,6 @@ Controller life cycle:
425 442
426 ##### Forms of use: 443 ##### Forms of use:
427 444
428 -- Recommended usage:  
429 -  
430 You can use Controller instance directly on GetBuilder value: 445 You can use Controller instance directly on GetBuilder value:
431 446
432 ```dart 447 ```dart
@@ -443,7 +458,7 @@ class Controller extends GetController { @@ -443,7 +458,7 @@ class Controller extends GetController {
443 static Controller get to => Get.find(); 458 static Controller get to => Get.find();
444 [...] 459 [...]
445 } 460 }
446 -// on stateful/stateless class 461 +// on you view:
447 GetBuilder<Controller>( 462 GetBuilder<Controller>(
448 init: Controller(), // use it only first time on each controller 463 init: Controller(), // use it only first time on each controller
449 builder: (_) => Text( 464 builder: (_) => Text(
@@ -469,14 +484,15 @@ GetBuilder<Controller>( @@ -469,14 +484,15 @@ GetBuilder<Controller>(
469 484
470 Controller controller = Controller(); 485 Controller controller = Controller();
471 [...] 486 [...]
472 -GetBuilder( // you dont need to type on this way 487 +GetBuilder<Controller>(
473 init: controller, //here 488 init: controller, //here
474 builder: (_) => Text( 489 builder: (_) => Text(
475 '${controller.counter}', // here 490 '${controller.counter}', // here
476 )), 491 )),
477 492
478 ``` 493 ```
479 -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! 494 +<!-- 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! -->
  495 +
480 496
481 If you want to refine a widget's update control with GetBuilder, you can assign them unique IDs: 497 If you want to refine a widget's update control with GetBuilder, you can assign them unique IDs:
482 ```dart 498 ```dart
@@ -609,33 +625,34 @@ Camila @@ -609,33 +625,34 @@ Camila
609 625
610 ``` 626 ```
611 627
612 -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.  
613 -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: 628 +Working with Lists using Get is the best and most enjoyable thing in the world. They 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.
  629 +You also don't need to use ".value" with lists, the amazing dart api allowed us to remove that, unfortunate 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.
  630 +
614 ```dart 631 ```dart
615 final list = List<User>().obs; 632 final list = List<User>().obs;
616 ``` 633 ```
617 -```dart  
618 -ListView.builder (  
619 -itemCount: list.value.lenght  
620 -```  
621 -or else create a "get" method for it and abandon "value" for life. example:  
622 634
623 ```dart 635 ```dart
624 -final _list = List<User>().obs;  
625 -List get list => _list.value;  
626 -```  
627 -```dart  
628 ListView.builder ( 636 ListView.builder (
629 itemCount: list.lenght 637 itemCount: list.lenght
630 ``` 638 ```
631 -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.  
632 639
633 -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. 640 +You don't have to work with sets if you don't want to. you can use the "assign 'and" assignAll "api.
  641 +The "assign" api will clear your list, and add a single object that you want to start there.
  642 +The "assignAll" api will clear the existing list and add any iterable objects that you inject into it.
  643 +
  644 +We could remove the obligation to use 'value' to String and int 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.
634 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. 645 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.
635 646
636 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. 647 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.
637 648
  649 +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.
  650 +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.
  651 +
  652 +
638 ## Simple Instance Manager 653 ## Simple Instance Manager
  654 +- Note: If you are using Get's State Manager, you don't have to worry about that, just read for information, but pay more attention to the bindings api, which will do all of this automatically for you.
  655 +
639 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: 656 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:
640 657
641 ```dart 658 ```dart
@@ -671,6 +688,78 @@ To remove a instance of Get: @@ -671,6 +688,78 @@ To remove a instance of Get:
671 Get.delete<Controller>(); 688 Get.delete<Controller>();
672 ``` 689 ```
673 690
  691 +## Bindings
  692 +One of the great differentials of this package, perhaps, is the possibility of full integration of the routes, state manager and dependency manager.
  693 +When a route is removed from the Stack, all controllers, variables, and instances of objects related to it are removed from memory. If you are using streams or timers, they will be closed automatically, and you don't have to worry about any of that.
  694 +In version 2.10 Get completely implemented the Bindings API.
  695 +Now you no longer need to use the init method. You don't even have to type your controllers if you don't want to. You can start your controllers and services in the appropriate place for that.
  696 +The Binding class is a class that will decouple dependency injection, while "binding" routes to the state manager and dependency manager.
  697 +This allows Get to know which screen is being displayed when a particular controller is used and to know where and how to dispose of it.
  698 +In addition, the Binding class will allow you to have SmartManager configuration control. You can configure the dependencies to be arranged when removing a route from the stack, or when the widget that used it is laid out, or neither. You will have intelligent dependency management working for you, but even so, you can configure it as you wish.
  699 +
  700 +#### To use this API you only need:
  701 +- Create a class and implements Binding
  702 +
  703 +```dart
  704 +class HomeBinding implements Bindings{
  705 +```
  706 +
  707 +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:
  708 +
  709 +```dart
  710 +class HomeBinding implements Bindings{
  711 + @override
  712 + void dependencies() {
  713 + Get.lazyPut<ControllerX>(() => ControllerX());
  714 + Get.lazyPut<Service>(()=> Api());
  715 + }
  716 +}
  717 +```
  718 +Now you just need to inform your route, that you will use that binding to make the connection between route manager, dependencies and states.
  719 +
  720 +- Using named routes:
  721 +```dart
  722 +namedRoutes: {
  723 + '/': GetRoute(Home(), binding: HomeBinding())
  724 +}
  725 +```
  726 +
  727 +- Using normal routes:
  728 +```dart
  729 +Get.to(Home(), binding: HomeBinding());
  730 +```
  731 +
  732 +There, you don't have to worry about memory management of your application anymore, Get will do it for you.
  733 +
  734 +## Workers:
  735 +Workers will assist you, triggering specific callbacks when an event occurs.
  736 +
  737 +
  738 +```dart
  739 +/// Called every time the variable $_ is changed
  740 +ever(count1, (_) => print("$_ has been changed"));
  741 +
  742 +/// Called only first time the variable $_ is changed
  743 +once(count1, (_) => print("$_ was changed once"));
  744 +
  745 +/// Anti DDos - Called every time the user stops typing for 1 second, for example.
  746 +debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1));
  747 +
  748 +/// Ignore all changes within 1 second.
  749 +interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
  750 +```
  751 +- ever
  752 +'ever' is called every time its variable is changed. That's it.
  753 +
  754 +- ever
  755 +'once' is called only the first time the variable has been changed.
  756 +
  757 +- debounce
  758 +'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.
  759 +
  760 +- interval
  761 +'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. debounce 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.
  762 +
674 763
675 ## Navigate with named routes: 764 ## Navigate with named routes:
676 - If you prefer to navigate by namedRoutes, Get also supports this. 765 - If you prefer to navigate by namedRoutes, Get also supports this.
@@ -1026,3 +1115,5 @@ See how simple it is: @@ -1026,3 +1115,5 @@ See how simple it is:
1026 1115
1027 1116
1028 This library will always be updated and implementing new features. Feel free to offer PRs and contribute to them. 1117 This library will always be updated and implementing new features. Feel free to offer PRs and contribute to them.
  1118 +
  1119 +<a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" > </a>

23.9 KB | W: | H:

22 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
@@ -6,6 +6,7 @@ export 'src/snackbar/snack.dart'; @@ -6,6 +6,7 @@ export 'src/snackbar/snack.dart';
6 export 'src/bottomsheet/bottomsheet.dart'; 6 export 'src/bottomsheet/bottomsheet.dart';
7 export 'src/snackbar/snack_route.dart'; 7 export 'src/snackbar/snack_route.dart';
8 export 'src/state/get_state.dart'; 8 export 'src/state/get_state.dart';
  9 +export 'src/state/mixin_state.dart';
9 export 'src/rx/rx_interface.dart'; 10 export 'src/rx/rx_interface.dart';
10 export 'src/rx/rx_impl.dart'; 11 export 'src/rx/rx_impl.dart';
11 export 'src/rx/rx_event.dart'; 12 export 'src/rx/rx_event.dart';
@@ -31,6 +31,7 @@ class Get { @@ -31,6 +31,7 @@ class Get {
31 Duration _defaultDurationTransition = Duration(milliseconds: 400); 31 Duration _defaultDurationTransition = Duration(milliseconds: 400);
32 bool _defaultGlobalState = true; 32 bool _defaultGlobalState = true;
33 RouteSettings _settings; 33 RouteSettings _settings;
  34 + SmartManagement smartManagement = SmartManagement.full;
34 35
35 ///Use Get.to instead of Navigator.push, Get.off instead of Navigator.pushReplacement, 36 ///Use Get.to instead of Navigator.push, Get.off instead of Navigator.pushReplacement,
36 ///Get.offAll instead of Navigator.pushAndRemoveUntil. For named routes just add "named" 37 ///Get.offAll instead of Navigator.pushAndRemoveUntil. For named routes just add "named"
@@ -607,10 +608,6 @@ class Get { @@ -607,10 +608,6 @@ class Get {
607 Get()._getController.setThemeMode(themeMode); 608 Get()._getController.setThemeMode(themeMode);
608 } 609 }
609 610
610 - Get.restartApp() {  
611 - Get()._getController.restartApp();  
612 - }  
613 -  
614 static GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey) { 611 static GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey) {
615 Get()._key = newKey; 612 Get()._key = newKey;
616 return Get()._key; 613 return Get()._key;
@@ -625,7 +622,7 @@ class Get { @@ -625,7 +622,7 @@ class Get {
625 } 622 }
626 623
627 Map<int, GlobalKey<NavigatorState>> _keys = {}; 624 Map<int, GlobalKey<NavigatorState>> _keys = {};
628 - 625 + UniqueKey mKey = UniqueKey();
629 static GlobalKey<NavigatorState> nestedKey(int key) { 626 static GlobalKey<NavigatorState> nestedKey(int key) {
630 Get()._keys.putIfAbsent(key, () => GlobalKey<NavigatorState>()); 627 Get()._keys.putIfAbsent(key, () => GlobalKey<NavigatorState>());
631 return Get()._keys[key]; 628 return Get()._keys[key];
@@ -646,14 +643,15 @@ class Get { @@ -646,14 +643,15 @@ class Get {
646 643
647 Map<dynamic, _FcBuilderFunc> _factory = {}; 644 Map<dynamic, _FcBuilderFunc> _factory = {};
648 645
649 - static void lazyPut<S>(_FcBuilderFunc function) {  
650 - Get()._factory.putIfAbsent(S, () => function); 646 + static void lazyPut<S>(_FcBuilderFunc<S> builder, {String tag}) {
  647 + String key = _getKey(S, tag);
  648 + Get()._factory.putIfAbsent(key, () => builder);
651 } 649 }
652 650
653 /// Inject class on Get Instance Manager 651 /// Inject class on Get Instance Manager
654 static S put<S>( 652 static S put<S>(
655 S dependency, { 653 S dependency, {
656 - String name, 654 + String tag,
657 bool overrideAbstract = false, 655 bool overrideAbstract = false,
658 _FcBuilderFunc<S> builder, 656 _FcBuilderFunc<S> builder,
659 }) { 657 }) {
@@ -661,9 +659,9 @@ class Get { @@ -661,9 +659,9 @@ class Get {
661 isSingleton: true, 659 isSingleton: true,
662 replace: overrideAbstract, 660 replace: overrideAbstract,
663 //?? (("$S" == "${dependency.runtimeType}") == false), 661 //?? (("$S" == "${dependency.runtimeType}") == false),
664 - name: name, 662 + name: tag,
665 builder: builder ?? (() => dependency)); 663 builder: builder ?? (() => dependency));
666 - return find<S>(name: name); 664 + return find<S>(tag: tag);
667 } 665 }
668 666
669 /// Create a new instance from builder class 667 /// Create a new instance from builder class
@@ -694,33 +692,77 @@ class Get { @@ -694,33 +692,77 @@ class Get {
694 } 692 }
695 } 693 }
696 694
697 - /// Find a instance from required class  
698 - static S find<S>({String name, _FcBuilderFunc<S> instance}) {  
699 - if (Get.isRegistred<S>(name: name)) { 695 + Map<String, String> routesKey = {};
  696 +
  697 + void removeDependencyByRoute(String routeName) async {
  698 + List<String> keysToRemove = [];
  699 + Get().routesKey.forEach((key, value) {
  700 + if (value == routeName && value != null) {
  701 + keysToRemove.add(key);
  702 + }
  703 + });
  704 + keysToRemove.forEach((element) async {
  705 + await Get.delete(key: element);
  706 + });
  707 + keysToRemove.forEach((element) {
  708 + Get().routesKey?.remove(element);
  709 + });
  710 + keysToRemove.clear();
  711 + }
  712 +
  713 + static bool isRouteDependecyNull<S>({String name}) {
  714 + return (Get().routesKey[_getKey(S, name)] == null);
  715 + }
  716 +
  717 + static bool isDependencyInit<S>({String name}) {
700 String key = _getKey(S, name); 718 String key = _getKey(S, name);
  719 + return Get().routesKey.containsKey(key);
  720 + }
  721 +
  722 + registerRouteInstance<S>({String tag}) {
  723 + // print("Register route [$S] as ${Get.currentRoute}");
  724 + Get().routesKey.putIfAbsent(_getKey(S, tag), () => Get.currentRoute);
  725 + }
  726 +
  727 + /// Find a instance from required class
  728 + static S find<S>({String tag, _FcBuilderFunc<S> instance}) {
  729 + String key = _getKey(S, tag);
  730 + if (Get.isRegistred<S>(tag: tag)) {
  731 + if (!isDependencyInit<S>()) {
  732 + Get().registerRouteInstance<S>(tag: tag);
  733 + }
  734 +
701 _FcBuilder builder = Get()._singl[key]; 735 _FcBuilder builder = Get()._singl[key];
702 if (builder == null) { 736 if (builder == null) {
703 - if (name == null) { 737 + if (tag == null) {
704 throw "class ${S.toString()} is not register"; 738 throw "class ${S.toString()} is not register";
705 } else { 739 } else {
706 - throw "class ${S.toString()} with name '$name' is not register"; 740 + throw "class ${S.toString()} with tag '$tag' is not register";
707 } 741 }
708 } 742 }
709 return Get()._singl[key].getSependency(); 743 return Get()._singl[key].getSependency();
710 } else { 744 } else {
711 - if (!Get()._factory.containsKey(S)) 745 + if (!Get()._factory.containsKey(key))
712 throw " $S not found. You need call Get.put<$S>($S()) before"; 746 throw " $S not found. You need call Get.put<$S>($S()) before";
713 747
714 if (isLogEnable) print('[GET] $S instance was created at that time'); 748 if (isLogEnable) print('[GET] $S instance was created at that time');
715 - S _value = Get.put<S>(Get()._factory[S].call() as S);  
716 - Get()._factory.remove(S); 749 + S _value = Get.put<S>(Get()._factory[key].call() as S);
  750 +
  751 + if (!isDependencyInit<S>()) {
  752 + Get().registerRouteInstance<S>(tag: tag);
  753 + }
  754 +
  755 + if (Get().smartManagement != SmartManagement.keepFactory) {
  756 + Get()._factory.remove(key);
  757 + }
  758 +
717 return _value; 759 return _value;
718 } 760 }
719 } 761 }
720 762
721 /// Remove dependency of [S] on dependency abstraction. For concrete class use Get.delete 763 /// Remove dependency of [S] on dependency abstraction. For concrete class use Get.delete
722 - static void remove<S>({String name}) {  
723 - String key = _getKey(S, name); 764 + static void remove<S>({String tag}) {
  765 + String key = _getKey(S, tag);
724 _FcBuilder builder = Get()._singl[key]; 766 _FcBuilder builder = Get()._singl[key];
725 final i = builder.dependency; 767 final i = builder.dependency;
726 768
@@ -740,42 +782,52 @@ class Get { @@ -740,42 +782,52 @@ class Get {
740 return name == null ? type.toString() : type.toString() + name; 782 return name == null ? type.toString() : type.toString() + name;
741 } 783 }
742 784
743 - static bool reset() { 785 + static bool reset(
  786 + {bool clearFactory = true, bool clearRouteBindings = true}) {
  787 + if (clearFactory) Get()._factory.clear();
  788 + if (clearRouteBindings) Get().routesKey.clear();
744 Get()._singl.clear(); 789 Get()._singl.clear();
745 return true; 790 return true;
746 } 791 }
747 792
748 /// Delete class instance on [S] and clean memory 793 /// Delete class instance on [S] and clean memory
749 - static Future<bool> delete<S>({String name}) async {  
750 - String key = _getKey(S, name); 794 + static Future<bool> delete<S>({String tag, String key}) async {
  795 + String newKey;
  796 + if (key == null) {
  797 + newKey = _getKey(S, tag);
  798 + } else {
  799 + newKey = key;
  800 + }
751 801
752 - if (!Get()._singl.containsKey(key)) {  
753 - print('Instance $key not found'); 802 + if (!Get()._singl.containsKey(newKey)) {
  803 + print('Instance $newKey not found');
754 return false; 804 return false;
755 } 805 }
756 806
757 - _FcBuilder builder = Get()._singl[key]; 807 + _FcBuilder builder = Get()._singl[newKey];
758 final i = builder.dependency; 808 final i = builder.dependency;
759 809
760 if (i is DisposableInterface || i is GetController) { 810 if (i is DisposableInterface || i is GetController) {
761 await i.onClose(); 811 await i.onClose();
762 - if (isLogEnable) print('[GET] onClose of $key called'); 812 + if (isLogEnable) print('[GET] onClose of $newKey called');
763 } 813 }
764 814
765 - Get()._singl.removeWhere((oldkey, value) => (oldkey == key));  
766 - if (Get()._singl.containsKey(key)) {  
767 - print('error on remove object $key'); 815 + Get()._singl.removeWhere((oldkey, value) => (oldkey == newKey));
  816 + if (Get()._singl.containsKey(newKey)) {
  817 + print('[GET] error on remove object $newKey');
768 } else { 818 } else {
769 - if (isLogEnable) print('[GET] $key deleted from memory'); 819 + if (isLogEnable) print('[GET] $newKey deleted from memory');
770 } 820 }
  821 + // Get().routesKey?.remove(key);
771 return true; 822 return true;
772 } 823 }
773 824
774 /// check if instance is registred 825 /// check if instance is registred
775 - static bool isRegistred<S>({String name}) =>  
776 - Get()._singl.containsKey(_getKey(S, name)); 826 + static bool isRegistred<S>({String tag}) =>
  827 + Get()._singl.containsKey(_getKey(S, tag));
777 828
778 - static bool isPrepared<S>() => Get()._factory.containsKey(S); 829 + static bool isPrepared<S>({String tag}) =>
  830 + Get()._factory.containsKey(_getKey(S, tag));
779 831
780 /// give access to Routing API from GetObserver 832 /// give access to Routing API from GetObserver
781 static Routing get routing => Get()._routing; 833 static Routing get routing => Get()._routing;
@@ -811,9 +863,6 @@ class Get { @@ -811,9 +863,6 @@ class Get {
811 863
812 static set obs(RxInterface observer) => Get()._obs = observer; 864 static set obs(RxInterface observer) => Get()._obs = observer;
813 865
814 - // /// give arguments from previous route  
815 - // static get previousArguments => Get()._routing.previousArgs;  
816 -  
817 /// give name from current route 866 /// give name from current route
818 static get currentRoute => Get()._routing.current; 867 static get currentRoute => Get()._routing.current;
819 868
@@ -909,4 +958,11 @@ class _FcBuilder<S> { @@ -909,4 +958,11 @@ class _FcBuilder<S> {
909 } 958 }
910 } 959 }
911 960
  961 +enum SmartManagement {
  962 + full,
  963 + onlyBuilder,
  964 + keepFactory,
  965 + // none,
  966 +}
  967 +
912 typedef _FcBuilderFunc<S> = S Function(); 968 typedef _FcBuilderFunc<S> = S Function();
@@ -4,7 +4,7 @@ import 'package:get/src/state/get_state.dart'; @@ -4,7 +4,7 @@ import 'package:get/src/state/get_state.dart';
4 4
5 class GetMaterialController extends GetController { 5 class GetMaterialController extends GetController {
6 ParseRoute parse = ParseRoute(); 6 ParseRoute parse = ParseRoute();
7 - Key key = UniqueKey(); 7 + Key key;
8 ThemeData theme; 8 ThemeData theme;
9 ThemeMode themeMode; 9 ThemeMode themeMode;
10 10
@@ -19,6 +19,7 @@ class GetMaterialController extends GetController { @@ -19,6 +19,7 @@ class GetMaterialController extends GetController {
19 } 19 }
20 20
21 void restartApp() { 21 void restartApp() {
  22 + print("restart chamado");
22 key = UniqueKey(); 23 key = UniqueKey();
23 update(this); 24 update(this);
24 } 25 }
@@ -36,6 +36,8 @@ class GetMaterialApp extends StatelessWidget { @@ -36,6 +36,8 @@ class GetMaterialApp extends StatelessWidget {
36 this.showSemanticsDebugger = false, 36 this.showSemanticsDebugger = false,
37 this.debugShowCheckedModeBanner = true, 37 this.debugShowCheckedModeBanner = true,
38 this.shortcuts, 38 this.shortcuts,
  39 + this.smartManagement = SmartManagement.full,
  40 + this.initialBinding,
39 this.routingCallback, 41 this.routingCallback,
40 this.defaultTransition, 42 this.defaultTransition,
41 // this.actions, 43 // this.actions,
@@ -92,6 +94,8 @@ class GetMaterialApp extends StatelessWidget { @@ -92,6 +94,8 @@ class GetMaterialApp extends StatelessWidget {
92 final VoidCallback onDispose; 94 final VoidCallback onDispose;
93 final bool enableLog; 95 final bool enableLog;
94 final bool popGesture; 96 final bool popGesture;
  97 + final SmartManagement smartManagement;
  98 + final Bindings initialBinding;
95 final Duration transitionDuration; 99 final Duration transitionDuration;
96 final bool defaultGlobalState; 100 final bool defaultGlobalState;
97 final Map<String, GetRoute> namedRoutes; 101 final Map<String, GetRoute> namedRoutes;
@@ -177,6 +181,8 @@ class GetMaterialApp extends StatelessWidget { @@ -177,6 +181,8 @@ class GetMaterialApp extends StatelessWidget {
177 onDispose?.call(); 181 onDispose?.call();
178 }, 182 },
179 initState: (i) { 183 initState: (i) {
  184 + initialBinding?.dependencies();
  185 + Get().smartManagement = smartManagement;
180 onInit?.call(); 186 onInit?.call();
181 if (namedRoutes != null) { 187 if (namedRoutes != null) {
182 namedRoutes.forEach((key, value) { 188 namedRoutes.forEach((key, value) {
@@ -195,7 +201,7 @@ class GetMaterialApp extends StatelessWidget { @@ -195,7 +201,7 @@ class GetMaterialApp extends StatelessWidget {
195 }, 201 },
196 builder: (_) { 202 builder: (_) {
197 return MaterialApp( 203 return MaterialApp(
198 - key: _.key, 204 + key: key,
199 navigatorKey: 205 navigatorKey:
200 (navigatorKey == null ? Get.key : Get.addKey(navigatorKey)), 206 (navigatorKey == null ? Get.key : Get.addKey(navigatorKey)),
201 home: home, 207 home: home,
@@ -96,6 +96,10 @@ class GetObserver extends NavigatorObserver { @@ -96,6 +96,10 @@ class GetObserver extends NavigatorObserver {
96 if (Get.isLogEnable) print("[BACK ROUTE] ${route?.settings?.name}"); 96 if (Get.isLogEnable) print("[BACK ROUTE] ${route?.settings?.name}");
97 } 97 }
98 98
  99 + if (Get().smartManagement == SmartManagement.full) {
  100 + Get().removeDependencyByRoute("${route?.settings?.name}");
  101 + }
  102 +
99 isSnackbar = false; 103 isSnackbar = false;
100 isDialog = false; 104 isDialog = false;
101 isBottomSheet = false; 105 isBottomSheet = false;
@@ -129,6 +133,10 @@ class GetObserver extends NavigatorObserver { @@ -129,6 +133,10 @@ class GetObserver extends NavigatorObserver {
129 if (Get.isLogEnable) print("[REPLACE ROUTE] ${oldRoute?.settings?.name}"); 133 if (Get.isLogEnable) print("[REPLACE ROUTE] ${oldRoute?.settings?.name}");
130 if (Get.isLogEnable) print("[NEW ROUTE] ${newRoute?.settings?.name}"); 134 if (Get.isLogEnable) print("[NEW ROUTE] ${newRoute?.settings?.name}");
131 135
  136 + if (Get().smartManagement == SmartManagement.full) {
  137 + Get().removeDependencyByRoute("${oldRoute?.settings?.name}");
  138 + }
  139 +
132 isSnackbar = false; 140 isSnackbar = false;
133 isDialog = false; 141 isDialog = false;
134 isBottomSheet = false; 142 isBottomSheet = false;
@@ -156,6 +164,11 @@ class GetObserver extends NavigatorObserver { @@ -156,6 +164,11 @@ class GetObserver extends NavigatorObserver {
156 void didRemove(Route route, Route previousRoute) { 164 void didRemove(Route route, Route previousRoute) {
157 super.didRemove(route, previousRoute); 165 super.didRemove(route, previousRoute);
158 if (Get.isLogEnable) print("[REMOVING ROUTE] ${route?.settings?.name}"); 166 if (Get.isLogEnable) print("[REMOVING ROUTE] ${route?.settings?.name}");
  167 +
  168 + if (Get().smartManagement == SmartManagement.full) {
  169 + Get().removeDependencyByRoute("${route?.settings?.name}");
  170 + }
  171 +
159 final routeSend = Routing( 172 final routeSend = Routing(
160 isBack: false, 173 isBack: false,
161 route: previousRoute, 174 route: previousRoute,
1 -// import '../../get.dart';  
2 -  
3 -// class Reaction extends Rx {  
4 -// dynamic Function() listener;  
5 -// void Function(dynamic) callback;  
6 -  
7 -// Reaction(this.listener, this.callback) : super() {  
8 -// subject.stream.listen((_) {  
9 -// callback(_);  
10 -// });  
11 -  
12 -// var previousObserver = Get.obs;  
13 -// Get.obs = this;  
14 -// listener();  
15 -// Get.obs = previousObserver;  
16 -// }  
17 -  
18 -// void dispose() {  
19 -// close();  
20 -// }  
21 -// }  
22 -  
23 -// class When extends Rx {  
24 -// dynamic Function() listener;  
25 -// void Function(dynamic) callback;  
26 -  
27 -// When(this.listener, this.callback) : super() {  
28 -// subject.stream.listen((_) {  
29 -// callback(_);  
30 -// dispose();  
31 -// });  
32 -  
33 -// var previousObserver = Get.obs;  
34 -// Get.obs = this;  
35 -// listener();  
36 -// Get.obs = previousObserver;  
37 -// }  
38 -  
39 -// void dispose() {  
40 -// close();  
41 -// }  
42 -// } 1 +import 'package:get/get.dart';
  2 +import 'rx_interface.dart';
  3 +import 'utils/debouncer.dart';
  4 +
  5 +void ever(RxInterface listener, Function(dynamic) callback) {
  6 + listener.subject.stream.listen((event) {
  7 + callback(event.$new);
  8 + });
  9 +}
  10 +
  11 +void once(RxInterface listener, Function(dynamic) callback) {
  12 + int times = 0;
  13 + listener.subject.stream.listen((event) {
  14 + times++;
  15 + if (times < 2) {
  16 + callback(event.$new);
  17 + }
  18 + });
  19 +}
  20 +
  21 +void interval(RxInterface listener, Function(dynamic) callback,
  22 + {Duration time}) {
  23 + bool debounceActive = false;
  24 + Duration timer = time ?? Duration(seconds: 1);
  25 +
  26 + listener.subject.stream.listen((event) async {
  27 + if (debounceActive) return null;
  28 + debounceActive = true;
  29 + await Future.delayed(timer);
  30 + debounceActive = false;
  31 + callback(event.$new);
  32 + });
  33 +}
  34 +
  35 +void debounce(RxInterface listener, Function(dynamic) callback,
  36 + {Duration time}) {
  37 + final _debouncer = Debouncer(delay: time ?? Duration(milliseconds: 800));
  38 + listener.subject.stream.listen((event) {
  39 + _debouncer(() {
  40 + callback(event.$new);
  41 + });
  42 + });
  43 +}
@@ -10,6 +10,7 @@ class GetX<T extends RxController> extends StatefulWidget { @@ -10,6 +10,7 @@ class GetX<T extends RxController> extends StatefulWidget {
10 // final Stream Function(T) stream; 10 // final Stream Function(T) stream;
11 // final StreamController Function(T) streamController; 11 // final StreamController Function(T) streamController;
12 final bool autoRemove; 12 final bool autoRemove;
  13 + final bool assignId;
13 final void Function(State state) initState, dispose, didChangeDependencies; 14 final void Function(State state) initState, dispose, didChangeDependencies;
14 final T init; 15 final T init;
15 const GetX({ 16 const GetX({
@@ -17,6 +18,7 @@ class GetX<T extends RxController> extends StatefulWidget { @@ -17,6 +18,7 @@ class GetX<T extends RxController> extends StatefulWidget {
17 this.global = true, 18 this.global = true,
18 this.autoRemove = true, 19 this.autoRemove = true,
19 this.initState, 20 this.initState,
  21 + this.assignId = false,
20 // this.stream, 22 // this.stream,
21 this.dispose, 23 this.dispose,
22 this.didChangeDependencies, 24 this.didChangeDependencies,
@@ -33,16 +35,21 @@ class _GetXState<T extends RxController> extends State<GetX<T>> { @@ -33,16 +35,21 @@ class _GetXState<T extends RxController> extends State<GetX<T>> {
33 bool isCreator = false; 35 bool isCreator = false;
34 36
35 _GetXState() { 37 _GetXState() {
36 - _observer = ListX(); 38 + _observer = Rx();
37 } 39 }
38 40
39 @override 41 @override
40 void initState() { 42 void initState() {
  43 + bool isPrepared = Get.isPrepared<T>();
  44 + bool isRegistred = Get.isRegistred<T>();
41 if (widget.global) { 45 if (widget.global) {
42 - if (Get.isPrepared<T>()) { 46 + // if (Get().smartManagement == SmartManagement.full) {
  47 + // Get.isDependencyInit<T>();
  48 + // }
  49 + if (isPrepared) {
43 isCreator = true; 50 isCreator = true;
44 controller = Get.find<T>(); 51 controller = Get.find<T>();
45 - } else if (Get.isRegistred<T>() && !Get.isPrepared<T>()) { 52 + } else if (isRegistred) {
46 controller = Get.find<T>(); 53 controller = Get.find<T>();
47 isCreator = false; 54 isCreator = false;
48 } else { 55 } else {
@@ -56,11 +63,7 @@ class _GetXState<T extends RxController> extends State<GetX<T>> { @@ -56,11 +63,7 @@ class _GetXState<T extends RxController> extends State<GetX<T>> {
56 } 63 }
57 if (widget.initState != null) widget.initState(this); 64 if (widget.initState != null) widget.initState(this);
58 if (isCreator) { 65 if (isCreator) {
59 - try {  
60 controller?.onInit(); 66 controller?.onInit();
61 - } catch (e) {  
62 - if (Get.isLogEnable) print("Failure on call onInit");  
63 - }  
64 } 67 }
65 68
66 _listenSubscription = _observer.subject.stream.listen((data) { 69 _listenSubscription = _observer.subject.stream.listen((data) {
@@ -73,8 +76,9 @@ class _GetXState<T extends RxController> extends State<GetX<T>> { @@ -73,8 +76,9 @@ class _GetXState<T extends RxController> extends State<GetX<T>> {
73 void dispose() { 76 void dispose() {
74 if (widget.dispose != null) widget.dispose(this); 77 if (widget.dispose != null) widget.dispose(this);
75 78
76 - if (isCreator) { 79 + if (isCreator || widget.assignId) {
77 if (widget.autoRemove && Get.isRegistred<T>()) { 80 if (widget.autoRemove && Get.isRegistred<T>()) {
  81 + print("DISPOSEEER CHAMADOOO");
78 // controller.onClose(); 82 // controller.onClose();
79 Get.delete<T>(); 83 Get.delete<T>();
80 } 84 }
@@ -92,7 +96,6 @@ class _GetXState<T extends RxController> extends State<GetX<T>> { @@ -92,7 +96,6 @@ class _GetXState<T extends RxController> extends State<GetX<T>> {
92 96
93 @override 97 @override
94 Widget build(BuildContext context) { 98 Widget build(BuildContext context) {
95 - // _observer.close();  
96 final observer = Get.obs; 99 final observer = Get.obs;
97 Get.obs = this._observer; 100 Get.obs = this._observer;
98 final result = widget.builder(controller); 101 final result = widget.builder(controller);
@@ -3,11 +3,11 @@ import 'package:get/src/get_main.dart'; @@ -3,11 +3,11 @@ import 'package:get/src/get_main.dart';
3 import 'rx_callbacks.dart'; 3 import 'rx_callbacks.dart';
4 import 'rx_interface.dart'; 4 import 'rx_interface.dart';
5 import 'rx_model.dart'; 5 import 'rx_model.dart';
6 -import 'utils/delegate_list.dart';  
7 6
8 class _StoredValue<T> implements RxInterface<T> { 7 class _StoredValue<T> implements RxInterface<T> {
9 StreamController<Change<T>> subject = StreamController<Change<T>>.broadcast(); 8 StreamController<Change<T>> subject = StreamController<Change<T>>.broadcast();
10 - StreamController<Change<T>> _changeCtl = StreamController<Change<T>>(); 9 + StreamController<Change<T>> _changeCtl =
  10 + StreamController<Change<T>>.broadcast();
11 Map<Stream<Change<T>>, StreamSubscription> _subscriptions = Map(); 11 Map<Stream<Change<T>>, StreamSubscription> _subscriptions = Map();
12 12
13 T _value; 13 T _value;
@@ -119,32 +119,22 @@ class MapX<Map> extends _StoredValue<Map> { @@ -119,32 +119,22 @@ class MapX<Map> extends _StoredValue<Map> {
119 // } 119 // }
120 // } 120 // }
121 121
122 -class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> { 122 +class ListX<E> extends Iterable<E> implements RxInterface<E> {
123 /// Create a list similar to `List<T>` 123 /// Create a list similar to `List<T>`
124 - ListX([int length]) : super(length != null ? List<E>(length) : List<E>()) {  
125 - _onChange = subject.stream.asBroadcastStream();  
126 - }  
127 124
128 - ListX.filled(int length, E fill, {bool growable: false})  
129 - : super(List<E>.filled(length, fill, growable: growable)) { 125 + ListX([List<E> initial]) {
  126 + _list = initial;
130 _onChange = subject.stream.asBroadcastStream(); 127 _onChange = subject.stream.asBroadcastStream();
131 } 128 }
132 129
133 - ListX.from(Iterable<E> items, {bool growable: true})  
134 - : super(List<E>.from(items, growable: growable)) {  
135 - _onChange = subject.stream.asBroadcastStream();  
136 - }  
137 -  
138 - ListX.union(Iterable<E> items, [E item]) : super(items?.toList() ?? <E>[]) {  
139 - if (item != null) add(item);  
140 - _onChange = subject.stream.asBroadcastStream();  
141 - } 130 + @override
  131 + Iterator<E> get iterator => _list.iterator;
142 132
143 - ListX.of(Iterable<E> items, {bool growable: true})  
144 - : super(List<E>.of(items, growable: growable)); 133 + @override
  134 + bool get isEmpty => _list.isEmpty;
145 135
146 - ListX.generate(int length, E generator(int index), {bool growable: true})  
147 - : super(List<E>.generate(length, generator, growable: growable)); 136 + @override
  137 + bool get isNotEmpty => _list.isNotEmpty;
148 138
149 Map<Stream<Change<E>>, StreamSubscription> _subscriptions = Map(); 139 Map<Stream<Change<E>>, StreamSubscription> _subscriptions = Map();
150 140
@@ -168,19 +158,24 @@ class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> { @@ -168,19 +158,24 @@ class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> {
168 if (condition is bool && condition) addAll(items); 158 if (condition is bool && condition) addAll(items);
169 } 159 }
170 160
171 - operator []=(int index, E value) {  
172 - super[index] = value;  
173 - if (Get.obs != null) {  
174 - Get.obs.addListener(subject.stream);  
175 - }  
176 - subject.add(Change<E>.set(item: value, pos: index)); 161 + operator []=(int index, E val) {
  162 + _list[index] = val;
  163 + subject.add(Change<E>.set($new: val, item: val, pos: index));
177 } 164 }
178 165
179 - void _add(E item) => super.add(item); 166 + E operator [](int index) {
  167 + return value[index];
  168 + }
180 169
181 void add(E item) { 170 void add(E item) {
182 - super.add(item);  
183 - subject.add(Change<E>.insert(item: item, pos: length - 1)); 171 + _list.add(item);
  172 + subject
  173 + .add(Change<E>.insert($new: item, item: item, pos: _list.length - 1));
  174 + }
  175 +
  176 + void addAll(List<E> item) {
  177 + _list.addAll(item);
  178 + subject.add(Change<E>.insert(item: _list.last, pos: _list.length - 1));
184 } 179 }
185 180
186 /// Adds only if [item] is not null. 181 /// Adds only if [item] is not null.
@@ -189,26 +184,60 @@ class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> { @@ -189,26 +184,60 @@ class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> {
189 } 184 }
190 185
191 void insert(int index, E item) { 186 void insert(int index, E item) {
192 - super.insert(index, item); 187 + _list.insert(index, item);
193 subject.add(Change<E>.insert(item: item, pos: index)); 188 subject.add(Change<E>.insert(item: item, pos: index));
194 } 189 }
195 190
  191 + void insertAll(int index, Iterable<E> iterable) {
  192 + _list.insertAll(index, iterable);
  193 + subject.add(Change<E>.insert(item: iterable.last, pos: index));
  194 + }
  195 +
  196 + int get length => value.length;
  197 +
  198 + /// Removes an item from the list.
  199 + ///
  200 + /// This is O(N) in the number of items in the list.
  201 + ///
  202 + /// Returns whether the item was present in the list.
196 bool remove(Object item) { 203 bool remove(Object item) {
197 - int pos = indexOf(item);  
198 - bool hasRemoved = super.remove(item); 204 + int pos = _list.indexOf(item);
  205 + bool hasRemoved = _list.remove(item);
199 if (hasRemoved) { 206 if (hasRemoved) {
200 subject.add(Change<E>.remove(item: item, pos: pos)); 207 subject.add(Change<E>.remove(item: item, pos: pos));
201 } 208 }
202 return hasRemoved; 209 return hasRemoved;
203 } 210 }
204 211
  212 + E removeAt(int index) {
  213 + E item = _list.removeAt(index);
  214 + subject.add(Change<E>.remove(item: item, pos: index));
  215 + return item;
  216 + }
  217 +
  218 + E removeLast() {
  219 + int pos = _list.indexOf(_list.last);
  220 + E item = _list.removeLast();
  221 + subject.add(Change<E>.remove(item: item, pos: pos));
  222 + return item;
  223 + }
  224 +
  225 + void removeRange(int start, int end) {
  226 + _list.removeRange(start, end);
  227 + subject.add(Change<E>.remove(item: null, pos: null));
  228 + }
  229 +
  230 + void removeWhere(bool Function(E) test) {
  231 + _list.removeWhere(test);
  232 + subject.add(Change<E>.remove(item: null, pos: null));
  233 + }
  234 +
205 void clear() { 235 void clear() {
206 - super.clear(); 236 + _list.clear();
207 subject.add(Change<E>.clear()); 237 subject.add(Change<E>.clear());
208 } 238 }
209 239
210 close() { 240 close() {
211 - clear();  
212 _subscriptions.forEach((observable, subscription) { 241 _subscriptions.forEach((observable, subscription) {
213 subscription.cancel(); 242 subscription.cancel();
214 }); 243 });
@@ -257,7 +286,7 @@ class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> { @@ -257,7 +286,7 @@ class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> {
257 if (Get.obs != null) { 286 if (Get.obs != null) {
258 Get.obs.addListener(subject.stream); 287 Get.obs.addListener(subject.stream);
259 } 288 }
260 - return this; 289 + return _list;
261 } 290 }
262 291
263 set v(E val) { 292 set v(E val) {
@@ -292,31 +321,208 @@ class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> { @@ -292,31 +321,208 @@ class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> {
292 321
293 @override 322 @override
294 void setCast(dynamic val) => v = val; 323 void setCast(dynamic val) => v = val;
  324 +
  325 + List<E> _list = <E>[];
295 } 326 }
296 327
297 -typedef bool Condition(); 328 +// class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> {
  329 +// /// Create a list similar to `List<T>`
  330 +// ListX([int length]) : super(length != null ? List<E>(length) : List<E>()) {
  331 +// _onChange = subject.stream.asBroadcastStream();
  332 +// }
298 333
299 -typedef E ChildrenListComposer<S, E>(S value); 334 +// ListX.filled(int length, E fill, {bool growable: false})
  335 +// : super(List<E>.filled(length, fill, growable: growable)) {
  336 +// _onChange = subject.stream.asBroadcastStream();
  337 +// }
300 338
301 -/// An observable list that is bound to another list [binding]  
302 -class BindingList<S, E> extends ListX<E> {  
303 - final ListX<S> binding; 339 +// ListX.from(Iterable<E> items, {bool growable: true})
  340 +// : super(List<E>.from(items, growable: growable)) {
  341 +// _onChange = subject.stream.asBroadcastStream();
  342 +// }
304 343
305 - final ChildrenListComposer<S, E> composer; 344 +// ListX.union(Iterable<E> items, [E item]) : super(items?.toList() ?? <E>[]) {
  345 +// if (item != null) add(item);
  346 +// _onChange = subject.stream.asBroadcastStream();
  347 +// }
306 348
307 - BindingList(this.binding, this.composer) {  
308 - for (S v in binding) _add(composer(v));  
309 - binding.onChange.listen((Change<S> n) {  
310 - if (n.op == ListChangeOp.add) {  
311 - insert(n.pos, composer(n.item));  
312 - } else if (n.op == ListChangeOp.remove) {  
313 - removeAt(n.pos);  
314 - } else if (n.op == ListChangeOp.clear) {  
315 - clear();  
316 - }  
317 - });  
318 - }  
319 -} 349 +// ListX.of(Iterable<E> items, {bool growable: true})
  350 +// : super(List<E>.of(items, growable: growable));
  351 +
  352 +// ListX.generate(int length, E generator(int index), {bool growable: true})
  353 +// : super(List<E>.generate(length, generator, growable: growable));
  354 +
  355 +// Map<Stream<Change<E>>, StreamSubscription> _subscriptions = Map();
  356 +
  357 +// // StreamSubscription _changectl = StreamSubscription();
  358 +
  359 +// StreamController<Change<E>> _changeCtl =
  360 +// StreamController<Change<E>>.broadcast();
  361 +
  362 +// @override
  363 +// StreamController<Change<E>> subject = StreamController<Change<E>>.broadcast();
  364 +
  365 +// /// Adds [item] only if [condition] resolves to true.
  366 +// void addIf(condition, E item) {
  367 +// if (condition is Condition) condition = condition();
  368 +// if (condition is bool && condition) add(item);
  369 +// }
  370 +
  371 +// /// Adds all [items] only if [condition] resolves to true.
  372 +// void addAllIf(condition, Iterable<E> items) {
  373 +// if (condition is Condition) condition = condition();
  374 +// if (condition is bool && condition) addAll(items);
  375 +// }
  376 +
  377 +// operator []=(int index, E value) {
  378 +// super[index] = value;
  379 +// if (Get.obs != null) {
  380 +// Get.obs.addListener(subject.stream);
  381 +// }
  382 +// subject.add(Change<E>.set(item: value, pos: index));
  383 +// }
  384 +
  385 +// void _add(E item) => super.add(item);
  386 +
  387 +// void add(E item) {
  388 +// super.add(item);
  389 +// subject.add(Change<E>.insert(item: item, pos: length - 1));
  390 +// }
  391 +
  392 +// /// Adds only if [item] is not null.
  393 +// void addNonNull(E item) {
  394 +// if (item != null) add(item);
  395 +// }
  396 +
  397 +// void insert(int index, E item) {
  398 +// super.insert(index, item);
  399 +// subject.add(Change<E>.insert(item: item, pos: index));
  400 +// }
  401 +
  402 +// bool remove(Object item) {
  403 +// int pos = indexOf(item);
  404 +// bool hasRemoved = super.remove(item);
  405 +// if (hasRemoved) {
  406 +// subject.add(Change<E>.remove(item: item, pos: pos));
  407 +// }
  408 +// return hasRemoved;
  409 +// }
  410 +
  411 +// void clear() {
  412 +// super.clear();
  413 +// subject.add(Change<E>.clear());
  414 +// }
  415 +
  416 +// close() {
  417 +// clear();
  418 +// _subscriptions.forEach((observable, subscription) {
  419 +// subscription.cancel();
  420 +// });
  421 +// _subscriptions.clear();
  422 +// subject.close();
  423 +// _changeCtl.close();
  424 +// }
  425 +
  426 +// /// Replaces all existing items of this list with [item]
  427 +// void assign(E item) {
  428 +// clear();
  429 +// add(item);
  430 +// }
  431 +
  432 +// /// Replaces all existing items of this list with [items]
  433 +// void assignAll(Iterable<E> items) {
  434 +// clear();
  435 +// addAll(items);
  436 +// }
  437 +
  438 +// /// A stream of record of changes to this list
  439 +// Stream<Change<E>> get onChange {
  440 +// final now = DateTime.now();
  441 +
  442 +// _onChange.skipWhile((m) => m.time.isBefore(now));
  443 +// return _changeCtl.stream.asBroadcastStream();
  444 +// }
  445 +
  446 +// Stream<Change<E>> _onChange;
  447 +
  448 +// addListener(Stream<Change<E>> rxGetx) {
  449 +// if (_subscriptions.containsKey(rxGetx)) {
  450 +// return;
  451 +// }
  452 +// _subscriptions[rxGetx] = rxGetx.listen((data) {
  453 +// subject.add(data);
  454 +// });
  455 +// }
  456 +
  457 +// List<E> get value => v as List<E>;
  458 +
  459 +// set value(List<E> va) => assignAll(va);
  460 +
  461 +// @override
  462 +// get v {
  463 +// if (Get.obs != null) {
  464 +// Get.obs.addListener(subject.stream);
  465 +// }
  466 +// return this;
  467 +// }
  468 +
  469 +// set v(E val) {
  470 +// assign(val);
  471 +// }
  472 +
  473 +// @override
  474 +// Stream<E> get stream => onChange.map((c) => c.item);
  475 +
  476 +// @override
  477 +// void bind(RxInterface<E> reactive) {
  478 +// v = reactive.v;
  479 +// reactive.stream.listen((va) => v = va);
  480 +// }
  481 +
  482 +// void bindStream(Stream<E> stream) => stream.listen((va) => v = va);
  483 +
  484 +// @override
  485 +// void bindOrSet(/* T | Stream<T> or Rx<T> */ other) {
  486 +// if (other is RxInterface<E>) {
  487 +// bind(other);
  488 +// } else if (other is Stream<E>) {
  489 +// bindStream(other.cast<E>());
  490 +// } else {
  491 +// v = other;
  492 +// }
  493 +// }
  494 +
  495 +// @override
  496 +// StreamSubscription<E> listen(ValueCallback<E> callback) =>
  497 +// stream.listen(callback);
  498 +
  499 +// @override
  500 +// void setCast(dynamic val) => v = val;
  501 +// }
  502 +
  503 +typedef bool Condition();
  504 +
  505 +typedef E ChildrenListComposer<S, E>(S value);
  506 +
  507 +// /// An observable list that is bound to another list [binding]
  508 +// class BindingList<S, E> extends ListX<E> {
  509 +// final ListX<S> binding;
  510 +
  511 +// final ChildrenListComposer<S, E> composer;
  512 +
  513 +// BindingList(this.binding, this.composer) {
  514 +// for (S v in binding) _add(composer(v));
  515 +// binding.onChange.listen((Change<S> n) {
  516 +// if (n.op == ListChangeOp.add) {
  517 +// insert(n.pos, composer(n.item));
  518 +// } else if (n.op == ListChangeOp.remove) {
  519 +// removeAt(n.pos);
  520 +// } else if (n.op == ListChangeOp.clear) {
  521 +// clear();
  522 +// }
  523 +// });
  524 +// }
  525 +// }
320 526
321 class BoolX<bool> extends _StoredValue<bool> { 527 class BoolX<bool> extends _StoredValue<bool> {
322 BoolX([bool initial]) { 528 BoolX([bool initial]) {
@@ -385,7 +591,7 @@ extension MapExtension on Map { @@ -385,7 +591,7 @@ extension MapExtension on Map {
385 extension ListExtension<E> on List<E> { 591 extension ListExtension<E> on List<E> {
386 ListX<E> get obs { 592 ListX<E> get obs {
387 if (this != null) 593 if (this != null)
388 - return ListX<E>()..assignAll(this); 594 + return ListX<E>([])..assignAll(this);
389 else 595 else
390 return ListX<E>(null); 596 return ListX<E>(null);
391 } 597 }
@@ -6,17 +6,15 @@ import 'rx_impl.dart'; @@ -6,17 +6,15 @@ import 'rx_impl.dart';
6 6
7 Widget obx(Widget Function() builder) { 7 Widget obx(Widget Function() builder) {
8 final b = builder; 8 final b = builder;
9 - return Obx(  
10 - builder: b,  
11 - ); 9 + return Obx(b);
12 } 10 }
13 11
14 class Obx extends StatefulWidget { 12 class Obx extends StatefulWidget {
15 final Widget Function() builder; 13 final Widget Function() builder;
16 14
17 - const Obx({ 15 + const Obx(
18 this.builder, 16 this.builder,
19 - }); 17 + );
20 _ObxState createState() => _ObxState(); 18 _ObxState createState() => _ObxState();
21 } 19 }
22 20
  1 +import 'dart:async';
  2 +
  3 +class Debouncer {
  4 + final Duration delay;
  5 + Timer _timer;
  6 +
  7 + Debouncer({this.delay});
  8 +
  9 + call(Function action) {
  10 + _timer?.cancel();
  11 + _timer = Timer(delay, action);
  12 + }
  13 +}
@@ -47,6 +47,7 @@ class GetBuilder<T extends GetController> extends StatefulWidget { @@ -47,6 +47,7 @@ class GetBuilder<T extends GetController> extends StatefulWidget {
47 final bool global; 47 final bool global;
48 final String id; 48 final String id;
49 final bool autoRemove; 49 final bool autoRemove;
  50 + final bool assignId;
50 final void Function(State state) initState, dispose, didChangeDependencies; 51 final void Function(State state) initState, dispose, didChangeDependencies;
51 final void Function(GetBuilder oldWidget, State state) didUpdateWidget; 52 final void Function(GetBuilder oldWidget, State state) didUpdateWidget;
52 final T init; 53 final T init;
@@ -56,6 +57,7 @@ class GetBuilder<T extends GetController> extends StatefulWidget { @@ -56,6 +57,7 @@ class GetBuilder<T extends GetController> extends StatefulWidget {
56 this.global = true, 57 this.global = true,
57 this.builder, 58 this.builder,
58 this.autoRemove = true, 59 this.autoRemove = true,
  60 + this.assignId = false,
59 this.initState, 61 this.initState,
60 this.dispose, 62 this.dispose,
61 this.id, 63 this.id,
@@ -118,7 +120,7 @@ class _GetBuilderState<T extends GetController> extends State<GetBuilder<T>> { @@ -118,7 +120,7 @@ class _GetBuilderState<T extends GetController> extends State<GetBuilder<T>> {
118 120
119 if (widget.dispose != null) widget.dispose(this); 121 if (widget.dispose != null) widget.dispose(this);
120 122
121 - if (isCreator) { 123 + if (isCreator || widget.assignId) {
122 if (widget.autoRemove && Get.isRegistred<T>()) { 124 if (widget.autoRemove && Get.isRegistred<T>()) {
123 // controller.onClose(); 125 // controller.onClose();
124 controller._allStates.remove(real); 126 controller._allStates.remove(real);
  1 +import 'package:flutter/widgets.dart';
  2 +import 'package:get/src/rx/rx_obx.dart';
  3 +import 'get_state.dart';
  4 +
  5 +class MixinBuilder<T extends GetController> extends StatelessWidget {
  6 + @required
  7 + final Widget Function(T) builder;
  8 + final bool global;
  9 + final String id;
  10 + final bool autoRemove;
  11 + final void Function(State state) initState, dispose, didChangeDependencies;
  12 + final void Function(GetBuilder oldWidget, State state) didUpdateWidget;
  13 + final T init;
  14 + const MixinBuilder({
  15 + Key key,
  16 + this.init,
  17 + this.global = true,
  18 + this.builder,
  19 + this.autoRemove = true,
  20 + this.initState,
  21 + this.dispose,
  22 + this.id,
  23 + this.didChangeDependencies,
  24 + this.didUpdateWidget,
  25 + }) : assert(builder != null),
  26 + super(key: key);
  27 +
  28 + @override
  29 + Widget build(BuildContext context) {
  30 + return GetBuilder<T>(
  31 + init: init,
  32 + global: global,
  33 + autoRemove: autoRemove,
  34 + initState: initState,
  35 + dispose: dispose,
  36 + id: id,
  37 + didChangeDependencies: didChangeDependencies,
  38 + didUpdateWidget: didUpdateWidget,
  39 + builder: (controller) => obx(() => builder.call(controller)));
  40 + }
  41 +}
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.7.1 3 +version: 2.10.0
4 homepage: https://github.com/jonataslaw/get 4 homepage: https://github.com/jonataslaw/get
5 5
6 environment: 6 environment: