Showing
16 changed files
with
621 additions
and
178 deletions
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> |
@@ -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 |
lib/src/rx/utils/debouncer.dart
0 → 100644
@@ -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); |
lib/src/state/mixin_state.dart
0 → 100644
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: |
-
Please register or login to post a comment