Jonny Borges
Committed by GitHub

Merge pull request #2115 from jonataslaw/update-code

improve code
@@ -20,6 +20,10 @@ version: 1.0.0+1 @@ -20,6 +20,10 @@ version: 1.0.0+1
20 environment: 20 environment:
21 sdk: ">=2.12.0 <3.0.0" 21 sdk: ">=2.12.0 <3.0.0"
22 22
  23 +dependency_overrides:
  24 + get:
  25 + path: ../
  26 +
23 dependencies: 27 dependencies:
24 flutter: 28 flutter:
25 sdk: flutter 29 sdk: flutter
@@ -33,6 +37,7 @@ dependencies: @@ -33,6 +37,7 @@ dependencies:
33 dev_dependencies: 37 dev_dependencies:
34 flutter_test: 38 flutter_test:
35 sdk: flutter 39 sdk: flutter
  40 + get_test: 4.0.1
36 41
37 # For information on the generic Dart part of this file, see the 42 # For information on the generic Dart part of this file, see the
38 # following page: https://dart.dev/tools/pub/pubspec 43 # following page: https://dart.dev/tools/pub/pubspec
1 import 'dart:async'; 1 import 'dart:async';
2 2
3 -import 'package:get/get.dart';  
4 import 'package:async/async.dart'; 3 import 'package:async/async.dart';
  4 +import 'package:get/get.dart';
5 5
6 class SplashService extends GetxService { 6 class SplashService extends GetxService {
7 final welcomeStr = ['GetX', 'Rules!']; 7 final welcomeStr = ['GetX', 'Rules!'];
1 -import 'package:example_nav2/app/modules/splash/controllers/splash_service.dart';  
2 -import 'package:example_nav2/app/modules/splash/views/splash_view.dart';  
3 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
4 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
5 3
  4 +import 'app/modules/splash/controllers/splash_service.dart';
  5 +import 'app/modules/splash/views/splash_view.dart';
6 import 'app/routes/app_pages.dart'; 6 import 'app/routes/app_pages.dart';
7 import 'services/auth_service.dart'; 7 import 'services/auth_service.dart';
8 8
@@ -76,3 +76,11 @@ mixin GetLifeCycleMixin { @@ -76,3 +76,11 @@ mixin GetLifeCycleMixin {
76 76
77 /// Allow track difference between GetxServices and GetxControllers 77 /// Allow track difference between GetxServices and GetxControllers
78 mixin GetxServiceMixin {} 78 mixin GetxServiceMixin {}
  79 +
  80 +/// Unlike GetxController, which serves to control events on each of its pages,
  81 +/// GetxService is not automatically disposed (nor can be removed with
  82 +/// Get.delete()).
  83 +/// It is ideal for situations where, once started, that service will
  84 +/// remain in memory, such as Auth control for example. Only way to remove
  85 +/// it is Get.reset().
  86 +abstract class GetxService with GetLifeCycleMixin, GetxServiceMixin {}
@@ -2,9 +2,9 @@ import 'dart:async'; @@ -2,9 +2,9 @@ import 'dart:async';
2 2
3 import 'package:flutter/foundation.dart'; 3 import 'package:flutter/foundation.dart';
4 import 'package:flutter/material.dart'; 4 import 'package:flutter/material.dart';
  5 +
5 import '../../../get.dart'; 6 import '../../../get.dart';
6 import '../../../get_state_manager/src/simple/list_notifier.dart'; 7 import '../../../get_state_manager/src/simple/list_notifier.dart';
7 -import 'get_navigator.dart';  
8 8
9 /// Enables the user to customize the intended pop behavior 9 /// Enables the user to customize the intended pop behavior
10 /// 10 ///
@@ -4,6 +4,21 @@ import '../../../get.dart'; @@ -4,6 +4,21 @@ import '../../../get.dart';
4 import '../router_report.dart'; 4 import '../router_report.dart';
5 import 'get_transition_mixin.dart'; 5 import 'get_transition_mixin.dart';
6 6
  7 +@optionalTypeArgs
  8 +mixin RouteReportMixin<T extends StatefulWidget> on State<T> {
  9 + @override
  10 + void initState() {
  11 + super.initState();
  12 + RouterReportManager.instance.reportCurrentRoute(this);
  13 + }
  14 +
  15 + @override
  16 + void dispose() {
  17 + super.dispose();
  18 + RouterReportManager.instance.reportRouteDispose(this);
  19 + }
  20 +}
  21 +
7 mixin PageRouteReportMixin<T> on Route<T> { 22 mixin PageRouteReportMixin<T> on Route<T> {
8 @override 23 @override
9 void install() { 24 void install() {
  1 +import 'package:flutter/material.dart';
  2 +
  3 +import '../router_report.dart';
  4 +import 'default_route.dart';
  5 +
  6 +class RouteReport extends StatefulWidget {
  7 + RouteReport({Key? key, required this.builder}) : super(key: key);
  8 + final WidgetBuilder builder;
  9 +
  10 + @override
  11 + _RouteReportState createState() => _RouteReportState();
  12 +}
  13 +
  14 +class _RouteReportState extends State<RouteReport> with RouteReportMixin {
  15 + @override
  16 + void initState() {
  17 + RouterReportManager.instance.reportCurrentRoute(this);
  18 + super.initState();
  19 + }
  20 +
  21 + @override
  22 + void dispose() {
  23 + RouterReportManager.instance.reportRouteDispose(this);
  24 + super.dispose();
  25 + }
  26 +
  27 + @override
  28 + Widget build(BuildContext context) {
  29 + return widget.builder(context);
  30 + }
  31 +}
@@ -102,9 +102,7 @@ mixin RxObjectMixin<T> on GetListenable<T> { @@ -102,9 +102,7 @@ mixin RxObjectMixin<T> on GetListenable<T> {
102 sentToStream = false; 102 sentToStream = false;
103 if (value == val && !firstRebuild) return; 103 if (value == val && !firstRebuild) return;
104 firstRebuild = false; 104 firstRebuild = false;
105 - // _value = val;  
106 sentToStream = true; 105 sentToStream = true;
107 - //TODO: Check this  
108 super.value = val; 106 super.value = val;
109 } 107 }
110 108
@@ -121,7 +119,6 @@ mixin RxObjectMixin<T> on GetListenable<T> { @@ -121,7 +119,6 @@ mixin RxObjectMixin<T> on GetListenable<T> {
121 cancelOnError: cancelOnError, 119 cancelOnError: cancelOnError,
122 ); 120 );
123 121
124 - //TODO: Change to refresh????  
125 subject.add(value); 122 subject.add(value);
126 123
127 return subscription; 124 return subscription;
@@ -140,53 +137,6 @@ mixin RxObjectMixin<T> on GetListenable<T> { @@ -140,53 +137,6 @@ mixin RxObjectMixin<T> on GetListenable<T> {
140 } 137 }
141 } 138 }
142 139
143 -//class RxNotifier<T> = RxInterface<T> with NotifyManager<T>;  
144 -  
145 -// mixin NotifyManager<T> {  
146 -// GetStream<T> subject = GetStream<T>();  
147 -// final _subscriptions = <GetStream, List<StreamSubscription>>{};  
148 -  
149 -// bool get canUpdate => _subscriptions.isNotEmpty;  
150 -  
151 -// /// This is an internal method.  
152 -// /// Subscribe to changes on the inner stream.  
153 -// void addListener(GetStream<T> rxGetx) {  
154 -// if (!_subscriptions.containsKey(rxGetx)) {  
155 -// final subs = rxGetx.listen((data) {  
156 -// if (!subject.isClosed) subject.add(data);  
157 -// });  
158 -// final listSubscriptions =  
159 -// _subscriptions[rxGetx] ??= <StreamSubscription>[];  
160 -// listSubscriptions.add(subs);  
161 -// }  
162 -// }  
163 -  
164 -// StreamSubscription<T> listen(  
165 -// void Function(T) onData, {  
166 -// Function? onError,  
167 -// void Function()? onDone,  
168 -// bool? cancelOnError,  
169 -// }) =>  
170 -// subject.listen(  
171 -// onData,  
172 -// onError: onError,  
173 -// onDone: onDone,  
174 -// cancelOnError: cancelOnError ?? false,  
175 -// );  
176 -  
177 -// /// Closes the subscriptions for this Rx, releasing the resources.  
178 -// void close() {  
179 -// _subscriptions.forEach((getStream, _subscriptions) {  
180 -// for (final subscription in _subscriptions) {  
181 -// subscription.cancel();  
182 -// }  
183 -// });  
184 -  
185 -// _subscriptions.clear();  
186 -// subject.close();  
187 -// }  
188 -// }  
189 -  
190 /// Base Rx class that manages all the stream logic for any Type. 140 /// Base Rx class that manages all the stream logic for any Type.
191 abstract class _RxImpl<T> extends GetListenable<T> with RxObjectMixin<T> { 141 abstract class _RxImpl<T> extends GetListenable<T> with RxObjectMixin<T> {
192 _RxImpl(T initial) : super(initial); 142 _RxImpl(T initial) : super(initial);
@@ -2,33 +2,15 @@ part of rx_types; @@ -2,33 +2,15 @@ part of rx_types;
2 2
3 /// This class is the foundation for all reactive (Rx) classes that makes Get 3 /// This class is the foundation for all reactive (Rx) classes that makes Get
4 /// so powerful. 4 /// so powerful.
5 -/// This interface is the contract that _RxImpl]<T> uses in all it's 5 +/// This interface is the contract that [_RxImpl]<T> uses in all it's
6 /// subclass. 6 /// subclass.
7 -abstract class RxInterface<T> {  
8 - //bool get canUpdate;  
9 -  
10 - /// Adds a listener to stream  
11 - void addListener(VoidCallback listener);  
12 - 7 +abstract class RxInterface<T> implements ValueListenable<T> {
13 /// Close the Rx Variable 8 /// Close the Rx Variable
14 void close(); 9 void close();
15 10
16 /// Calls `callback` with current value, when the value changes. 11 /// Calls `callback` with current value, when the value changes.
17 StreamSubscription<T> listen(void Function(T event) onData, 12 StreamSubscription<T> listen(void Function(T event) onData,
18 {Function? onError, void Function()? onDone, bool? cancelOnError}); 13 {Function? onError, void Function()? onDone, bool? cancelOnError});
19 -  
20 - /// Avoids an unsafe usage of the `proxy`  
21 - // static T notifyChildren<T>(RxNotifier observer, ValueGetter<T> builder) {  
22 - // final _observer = RxInterface.proxy;  
23 - // RxInterface.proxy = observer;  
24 - // final result = builder();  
25 - // if (!observer.canUpdate) {  
26 - // RxInterface.proxy = _observer;  
27 - // throw ObxError();  
28 - // }  
29 - // RxInterface.proxy = _observer;  
30 - // return result;  
31 - // }  
32 } 14 }
33 15
34 class ObxError { 16 class ObxError {
1 library get_state_manager; 1 library get_state_manager;
2 2
3 -export 'src/rx_flutter/rx_disposable.dart';  
4 export 'src/rx_flutter/rx_getx_widget.dart'; 3 export 'src/rx_flutter/rx_getx_widget.dart';
5 export 'src/rx_flutter/rx_notifier.dart'; 4 export 'src/rx_flutter/rx_notifier.dart';
6 export 'src/rx_flutter/rx_obx_widget.dart'; 5 export 'src/rx_flutter/rx_obx_widget.dart';
@@ -9,5 +8,4 @@ export 'src/simple/get_controllers.dart'; @@ -9,5 +8,4 @@ export 'src/simple/get_controllers.dart';
9 export 'src/simple/get_responsive.dart'; 8 export 'src/simple/get_responsive.dart';
10 export 'src/simple/get_state.dart'; 9 export 'src/simple/get_state.dart';
11 export 'src/simple/get_view.dart'; 10 export 'src/simple/get_view.dart';
12 -export 'src/simple/mixin_state.dart';  
13 export 'src/simple/simple_builder.dart'; 11 export 'src/simple/simple_builder.dart';
1 -import '../../../get_instance/src/lifecycle.dart';  
2 -  
3 -/// Unlike GetxController, which serves to control events on each of its pages,  
4 -/// GetxService is not automatically disposed (nor can be removed with  
5 -/// Get.delete()).  
6 -/// It is ideal for situations where, once started, that service will  
7 -/// remain in memory, such as Auth control for example. Only way to remove  
8 -/// it is Get.reset().  
9 -abstract class GetxService with GetLifeCycleMixin, GetxServiceMixin {}  
10 -  
11 -// abstract class DisposableInterface with GetLifeCycleMixin {}  
@@ -113,20 +113,25 @@ class GetXState<T extends GetLifeCycleMixin> extends State<GetX<T>> { @@ -113,20 +113,25 @@ class GetXState<T extends GetLifeCycleMixin> extends State<GetX<T>> {
113 disposer(); 113 disposer();
114 } 114 }
115 115
  116 + disposers.clear();
  117 +
116 controller = null; 118 controller = null;
117 _isCreator = null; 119 _isCreator = null;
118 super.dispose(); 120 super.dispose();
119 } 121 }
120 122
121 void _update() { 123 void _update() {
122 - setState(() {}); 124 + if (mounted) {
  125 + setState(() {});
  126 + }
123 } 127 }
124 128
125 final disposers = <Disposer>[]; 129 final disposers = <Disposer>[];
126 130
127 @override 131 @override
128 - Widget build(BuildContext context) => NotifierManager.instance  
129 - .exchange(disposers, _update, () => widget.builder(controller!)); 132 + Widget build(BuildContext context) => Notifier.instance.append(
  133 + NotifyData(disposers: disposers, updater: _update),
  134 + () => widget.builder(controller!));
130 135
131 @override 136 @override
132 void debugFillProperties(DiagnosticPropertiesBuilder properties) { 137 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
@@ -3,6 +3,7 @@ import 'dart:async'; @@ -3,6 +3,7 @@ import 'dart:async';
3 import 'package:flutter/foundation.dart'; 3 import 'package:flutter/foundation.dart';
4 import 'package:flutter/material.dart'; 4 import 'package:flutter/material.dart';
5 5
  6 +import '../../../get_rx/src/rx_types/rx_types.dart';
6 import '../../../instance_manager.dart'; 7 import '../../../instance_manager.dart';
7 import '../../get_state_manager.dart'; 8 import '../../get_state_manager.dart';
8 import '../simple/list_notifier.dart'; 9 import '../simple/list_notifier.dart';
@@ -78,8 +79,7 @@ mixin StateMixin<T> on ListNotifier { @@ -78,8 +79,7 @@ mixin StateMixin<T> on ListNotifier {
78 } 79 }
79 } 80 }
80 81
81 -class GetListenable<T> extends ListNotifierSingle  
82 - implements ValueListenable<T> { 82 +class GetListenable<T> extends ListNotifierSingle implements RxInterface<T> {
83 GetListenable(T val) : _value = val; 83 GetListenable(T val) : _value = val;
84 84
85 StreamController<T>? _controller; 85 StreamController<T>? _controller;
@@ -96,6 +96,7 @@ class GetListenable<T> extends ListNotifierSingle @@ -96,6 +96,7 @@ class GetListenable<T> extends ListNotifierSingle
96 _controller?.add(_value); 96 _controller?.add(_value);
97 } 97 }
98 98
  99 + @override
99 @mustCallSuper 100 @mustCallSuper
100 void close() { 101 void close() {
101 removeListener(_streamListener); 102 removeListener(_streamListener);
@@ -132,6 +133,7 @@ class GetListenable<T> extends ListNotifierSingle @@ -132,6 +133,7 @@ class GetListenable<T> extends ListNotifierSingle
132 return value; 133 return value;
133 } 134 }
134 135
  136 + @override
135 StreamSubscription<T> listen( 137 StreamSubscription<T> listen(
136 void Function(T)? onData, { 138 void Function(T)? onData, {
137 Function? onError, 139 Function? onError,
@@ -188,6 +190,8 @@ class Value<T> extends ListNotifier @@ -188,6 +190,8 @@ class Value<T> extends ListNotifier
188 dynamic toJson() => (value as dynamic)?.toJson(); 190 dynamic toJson() => (value as dynamic)?.toJson();
189 } 191 }
190 192
  193 +/// GetNotifier has a native status and state implementation, with the
  194 +/// Get Lifecycle
191 abstract class GetNotifier<T> extends Value<T> with GetLifeCycleMixin { 195 abstract class GetNotifier<T> extends Value<T> with GetLifeCycleMixin {
192 GetNotifier(T initial) : super(initial); 196 GetNotifier(T initial) : super(initial);
193 } 197 }
@@ -198,6 +202,7 @@ extension StateExt<T> on StateMixin<T> { @@ -198,6 +202,7 @@ extension StateExt<T> on StateMixin<T> {
198 Widget Function(String? error)? onError, 202 Widget Function(String? error)? onError,
199 Widget? onLoading, 203 Widget? onLoading,
200 Widget? onEmpty, 204 Widget? onEmpty,
  205 + WidgetBuilder? onCustom,
201 }) { 206 }) {
202 return Observer(builder: (_) { 207 return Observer(builder: (_) {
203 if (status.isLoading) { 208 if (status.isLoading) {
@@ -210,6 +215,11 @@ extension StateExt<T> on StateMixin<T> { @@ -210,6 +215,11 @@ extension StateExt<T> on StateMixin<T> {
210 return onEmpty != null 215 return onEmpty != null
211 ? onEmpty 216 ? onEmpty
212 : SizedBox.shrink(); // Also can be widget(null); but is risky 217 : SizedBox.shrink(); // Also can be widget(null); but is risky
  218 + } else if (status.isSuccess) {
  219 + return widget(value);
  220 + } else if (status.isCustom) {
  221 + return onCustom?.call(_) ??
  222 + SizedBox.shrink(); // Also can be widget(null); but is risky
213 } 223 }
214 return widget(value); 224 return widget(value);
215 }); 225 });
@@ -246,6 +256,7 @@ extension StatusDataExt<T> on GetState<T> { @@ -246,6 +256,7 @@ extension StatusDataExt<T> on GetState<T> {
246 bool get isSuccess => this is SuccessState; 256 bool get isSuccess => this is SuccessState;
247 bool get isError => this is ErrorState; 257 bool get isError => this is ErrorState;
248 bool get isEmpty => this is EmptyState; 258 bool get isEmpty => this is EmptyState;
  259 + bool get isCustom => !isLoading && !isSuccess && !isError && !isEmpty;
249 String get errorMessage { 260 String get errorMessage {
250 final isError = this is ErrorState; 261 final isError = this is ErrorState;
251 if (isError) { 262 if (isError) {
@@ -26,6 +26,8 @@ abstract class GetxController extends ListNotifier with GetLifeCycleMixin { @@ -26,6 +26,8 @@ abstract class GetxController extends ListNotifier with GetLifeCycleMixin {
26 } 26 }
27 } 27 }
28 28
  29 +/// this mixin allow to fetch data when the scroll is at the bottom or on the
  30 +/// top
29 mixin ScrollMixin on GetLifeCycleMixin { 31 mixin ScrollMixin on GetLifeCycleMixin {
30 final ScrollController scroll = ScrollController(); 32 final ScrollController scroll = ScrollController();
31 33
@@ -59,8 +61,10 @@ mixin ScrollMixin on GetLifeCycleMixin { @@ -59,8 +61,10 @@ mixin ScrollMixin on GetLifeCycleMixin {
59 } 61 }
60 } 62 }
61 63
  64 + /// this method is called when the scroll is at the bottom
62 Future<void> onEndScroll(); 65 Future<void> onEndScroll();
63 66
  67 + /// this method is called when the scroll is at the top
64 Future<void> onTopScroll(); 68 Future<void> onTopScroll();
65 69
66 @override 70 @override
@@ -70,13 +74,17 @@ mixin ScrollMixin on GetLifeCycleMixin { @@ -70,13 +74,17 @@ mixin ScrollMixin on GetLifeCycleMixin {
70 } 74 }
71 } 75 }
72 76
  77 +/// A clean controller to be used with only Rx variables
73 abstract class RxController with GetLifeCycleMixin {} 78 abstract class RxController with GetLifeCycleMixin {}
74 79
  80 +/// A recommended way to use Getx with Future fetching
75 abstract class StateController<T> extends GetxController with StateMixin<T> {} 81 abstract class StateController<T> extends GetxController with StateMixin<T> {}
76 82
  83 +/// A controller with super lifecycles (including native lifecycles) and StateMixins
77 abstract class SuperController<T> extends FullLifeCycleController 84 abstract class SuperController<T> extends FullLifeCycleController
78 with FullLifeCycleMixin, StateMixin<T> {} 85 with FullLifeCycleMixin, StateMixin<T> {}
79 86
  87 +/// A controller with super lifecycles (including native lifecycles)
80 abstract class FullLifeCycleController extends GetxController 88 abstract class FullLifeCycleController extends GetxController
81 with 89 with
82 // ignore: prefer_mixin 90 // ignore: prefer_mixin
@@ -116,8 +124,8 @@ mixin FullLifeCycleMixin on FullLifeCycleController { @@ -116,8 +124,8 @@ mixin FullLifeCycleMixin on FullLifeCycleController {
116 } 124 }
117 } 125 }
118 126
119 - void onResumed();  
120 - void onPaused();  
121 - void onInactive();  
122 - void onDetached(); 127 + void onResumed() {}
  128 + void onPaused() {}
  129 + void onInactive() {}
  130 + void onDetached() {}
123 } 131 }
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
2 2
3 import '../../../instance_manager.dart'; 3 import '../../../instance_manager.dart';
4 import '../../get_state_manager.dart'; 4 import '../../get_state_manager.dart';
  5 +import 'list_notifier.dart';
5 6
6 typedef InitBuilder<T> = T Function(); 7 typedef InitBuilder<T> = T Function();
7 8
@@ -37,7 +38,7 @@ class GetBuilder<T extends GetxController> extends StatelessWidget { @@ -37,7 +38,7 @@ class GetBuilder<T extends GetxController> extends StatelessWidget {
37 final void Function(BindElement<T> state)? initState, 38 final void Function(BindElement<T> state)? initState,
38 dispose, 39 dispose,
39 didChangeDependencies; 40 didChangeDependencies;
40 - final void Function(BindWrapper<T> oldWidget, BindElement<T> state)? 41 + final void Function(Binder<T> oldWidget, BindElement<T> state)?
41 didUpdateWidget; 42 didUpdateWidget;
42 final T? init; 43 final T? init;
43 44
@@ -59,7 +60,7 @@ class GetBuilder<T extends GetxController> extends StatelessWidget { @@ -59,7 +60,7 @@ class GetBuilder<T extends GetxController> extends StatelessWidget {
59 60
60 @override 61 @override
61 Widget build(BuildContext context) { 62 Widget build(BuildContext context) {
62 - return BindWrapper( 63 + return Binder(
63 init: init == null ? null : () => init!, 64 init: init == null ? null : () => init!,
64 global: global, 65 global: global,
65 autoRemove: autoRemove, 66 autoRemove: autoRemove,
@@ -108,7 +109,7 @@ abstract class Bind<T> extends StatelessWidget { @@ -108,7 +109,7 @@ abstract class Bind<T> extends StatelessWidget {
108 final void Function(BindElement<T> state)? initState, 109 final void Function(BindElement<T> state)? initState,
109 dispose, 110 dispose,
110 didChangeDependencies; 111 didChangeDependencies;
111 - final void Function(BindWrapper<T> oldWidget, BindElement<T> state)? 112 + final void Function(Binder<T> oldWidget, BindElement<T> state)?
112 didUpdateWidget; 113 didUpdateWidget;
113 114
114 final Widget? child; 115 final Widget? child;
@@ -193,8 +194,7 @@ abstract class Bind<T> extends StatelessWidget { @@ -193,8 +194,7 @@ abstract class Bind<T> extends StatelessWidget {
193 void Function(BindElement<T> state)? initState, 194 void Function(BindElement<T> state)? initState,
194 void Function(BindElement<T> state)? dispose, 195 void Function(BindElement<T> state)? dispose,
195 void Function(BindElement<T> state)? didChangeDependencies, 196 void Function(BindElement<T> state)? didChangeDependencies,
196 - void Function(BindWrapper<T> oldWidget, BindElement<T> state)?  
197 - didUpdateWidget, 197 + void Function(Binder<T> oldWidget, BindElement<T> state)? didUpdateWidget,
198 }) => 198 }) =>
199 _FactoryBind<T>( 199 _FactoryBind<T>(
200 // key: key, 200 // key: key,
@@ -218,7 +218,7 @@ abstract class Bind<T> extends StatelessWidget { @@ -218,7 +218,7 @@ abstract class Bind<T> extends StatelessWidget {
218 // Object Function(T value)? filter, 218 // Object Function(T value)? filter,
219 }) { 219 }) {
220 final inheritedElement = 220 final inheritedElement =
221 - context.getElementForInheritedWidgetOfExactType<BindWrapper<T>>() 221 + context.getElementForInheritedWidgetOfExactType<Binder<T>>()
222 as BindElement<T>?; 222 as BindElement<T>?;
223 223
224 if (inheritedElement == null) { 224 if (inheritedElement == null) {
@@ -265,7 +265,7 @@ class _FactoryBind<T> extends Bind<T> { @@ -265,7 +265,7 @@ class _FactoryBind<T> extends Bind<T> {
265 dispose, 265 dispose,
266 didChangeDependencies; 266 didChangeDependencies;
267 @override 267 @override
268 - final void Function(BindWrapper<T> oldWidget, BindElement<T> state)? 268 + final void Function(Binder<T> oldWidget, BindElement<T> state)?
269 didUpdateWidget; 269 didUpdateWidget;
270 270
271 @override 271 @override
@@ -307,7 +307,7 @@ class _FactoryBind<T> extends Bind<T> { @@ -307,7 +307,7 @@ class _FactoryBind<T> extends Bind<T> {
307 307
308 @override 308 @override
309 Widget build(BuildContext context) { 309 Widget build(BuildContext context) {
310 - return BindWrapper<T>( 310 + return Binder<T>(
311 init: init, 311 init: init,
312 global: global, 312 global: global,
313 autoRemove: autoRemove, 313 autoRemove: autoRemove,
@@ -340,12 +340,12 @@ class Binds extends StatelessWidget { @@ -340,12 +340,12 @@ class Binds extends StatelessWidget {
340 binds.reversed.fold(child, (acc, e) => e._copyWithChild(acc)); 340 binds.reversed.fold(child, (acc, e) => e._copyWithChild(acc));
341 } 341 }
342 342
343 -class BindWrapper<T> extends InheritedWidget { 343 +class Binder<T> extends InheritedWidget {
344 /// Create an inherited widget that updates its dependents when [controller] 344 /// Create an inherited widget that updates its dependents when [controller]
345 /// sends notifications. 345 /// sends notifications.
346 /// 346 ///
347 /// The [child] argument is required 347 /// The [child] argument is required
348 - const BindWrapper({ 348 + const Binder({
349 Key? key, 349 Key? key,
350 required Widget child, 350 required Widget child,
351 this.init, 351 this.init,
@@ -371,11 +371,11 @@ class BindWrapper<T> extends InheritedWidget { @@ -371,11 +371,11 @@ class BindWrapper<T> extends InheritedWidget {
371 final void Function(BindElement<T> state)? initState, 371 final void Function(BindElement<T> state)? initState,
372 dispose, 372 dispose,
373 didChangeDependencies; 373 didChangeDependencies;
374 - final void Function(BindWrapper<T> oldWidget, BindElement<T> state)? 374 + final void Function(Binder<T> oldWidget, BindElement<T> state)?
375 didUpdateWidget; 375 didUpdateWidget;
376 376
377 @override 377 @override
378 - bool updateShouldNotify(BindWrapper<T> oldWidget) { 378 + bool updateShouldNotify(Binder<T> oldWidget) {
379 return oldWidget.id != id || 379 return oldWidget.id != id ||
380 oldWidget.global != global || 380 oldWidget.global != global ||
381 oldWidget.autoRemove != autoRemove || 381 oldWidget.autoRemove != autoRemove ||
@@ -389,10 +389,12 @@ class BindWrapper<T> extends InheritedWidget { @@ -389,10 +389,12 @@ class BindWrapper<T> extends InheritedWidget {
389 /// The BindElement is responsible for injecting dependencies into the widget 389 /// The BindElement is responsible for injecting dependencies into the widget
390 /// tree so that they can be observed 390 /// tree so that they can be observed
391 class BindElement<T> extends InheritedElement { 391 class BindElement<T> extends InheritedElement {
392 - BindElement(BindWrapper<T> widget) : super(widget) { 392 + BindElement(Binder<T> widget) : super(widget) {
393 initState(); 393 initState();
394 } 394 }
395 395
  396 + final disposers = <Disposer>[];
  397 +
396 InitBuilder<T>? _controllerBuilder; 398 InitBuilder<T>? _controllerBuilder;
397 399
398 T? _controller; 400 T? _controller;
@@ -486,6 +488,12 @@ class BindElement<T> extends InheritedElement { @@ -486,6 +488,12 @@ class BindElement<T> extends InheritedElement {
486 } 488 }
487 } 489 }
488 490
  491 + for (final disposer in disposers) {
  492 + disposer();
  493 + }
  494 +
  495 + disposers.clear();
  496 +
489 _remove?.call(); 497 _remove?.call();
490 _controller = null; 498 _controller = null;
491 _isCreator = null; 499 _isCreator = null;
@@ -497,12 +505,12 @@ class BindElement<T> extends InheritedElement { @@ -497,12 +505,12 @@ class BindElement<T> extends InheritedElement {
497 } 505 }
498 506
499 @override 507 @override
500 - BindWrapper<T> get widget => super.widget as BindWrapper<T>; 508 + Binder<T> get widget => super.widget as Binder<T>;
501 509
502 var _dirty = false; 510 var _dirty = false;
503 511
504 @override 512 @override
505 - void update(BindWrapper<T> newWidget) { 513 + void update(Binder<T> newWidget) {
506 final oldNotifier = widget.id; 514 final oldNotifier = widget.id;
507 final newNotifier = newWidget.id; 515 final newNotifier = newWidget.id;
508 if (oldNotifier != newNotifier && _wasStarted) { 516 if (oldNotifier != newNotifier && _wasStarted) {
@@ -523,7 +531,11 @@ class BindElement<T> extends InheritedElement { @@ -523,7 +531,11 @@ class BindElement<T> extends InheritedElement {
523 if (_dirty) { 531 if (_dirty) {
524 notifyClients(widget); 532 notifyClients(widget);
525 } 533 }
  534 + // return Notifier.instance.notifyAppend(
  535 + // NotifyData(
  536 + // disposers: disposers, updater: getUpdate, throwException: false),
526 return super.build(); 537 return super.build();
  538 + //);
527 } 539 }
528 540
529 void getUpdate() { 541 void getUpdate() {
@@ -532,7 +544,7 @@ class BindElement<T> extends InheritedElement { @@ -532,7 +544,7 @@ class BindElement<T> extends InheritedElement {
532 } 544 }
533 545
534 @override 546 @override
535 - void notifyClients(BindWrapper<T> oldWidget) { 547 + void notifyClients(Binder<T> oldWidget) {
536 super.notifyClients(oldWidget); 548 super.notifyClients(oldWidget);
537 _dirty = false; 549 _dirty = false;
538 } 550 }
@@ -12,10 +12,14 @@ typedef GetStateUpdate = void Function(); @@ -12,10 +12,14 @@ typedef GetStateUpdate = void Function();
12 class ListNotifier extends Listenable 12 class ListNotifier extends Listenable
13 with ListNotifierSingleMixin, ListNotifierGroupMixin {} 13 with ListNotifierSingleMixin, ListNotifierGroupMixin {}
14 14
  15 +/// A Notifier with single listeners
15 class ListNotifierSingle = ListNotifier with ListNotifierSingleMixin; 16 class ListNotifierSingle = ListNotifier with ListNotifierSingleMixin;
16 17
  18 +/// A notifier with group of listeners identified by id
17 class ListNotifierGroup = ListNotifier with ListNotifierGroupMixin; 19 class ListNotifierGroup = ListNotifier with ListNotifierGroupMixin;
18 20
  21 +/// This mixin add to Listenable the addListener, removerListener and
  22 +/// containsListener implementation
19 mixin ListNotifierSingleMixin on Listenable { 23 mixin ListNotifierSingleMixin on Listenable {
20 List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[]; 24 List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[];
21 25
@@ -44,12 +48,12 @@ mixin ListNotifierSingleMixin on Listenable { @@ -44,12 +48,12 @@ mixin ListNotifierSingleMixin on Listenable {
44 48
45 @protected 49 @protected
46 void reportRead() { 50 void reportRead() {
47 - NotifierManager.instance.notify(this); 51 + Notifier.instance.read(this);
48 } 52 }
49 53
50 @protected 54 @protected
51 void reportAdd(VoidCallback disposer) { 55 void reportAdd(VoidCallback disposer) {
52 - NotifierManager.instance.reportAdd(disposer); 56 + Notifier.instance.add(disposer);
53 } 57 }
54 58
55 void _notifyUpdate() { 59 void _notifyUpdate() {
@@ -96,7 +100,7 @@ mixin ListNotifierGroupMixin on Listenable { @@ -96,7 +100,7 @@ mixin ListNotifierGroupMixin on Listenable {
96 @protected 100 @protected
97 void notifyGroupChildrens(Object id) { 101 void notifyGroupChildrens(Object id) {
98 assert(_debugAssertNotDisposed()); 102 assert(_debugAssertNotDisposed());
99 - NotifierManager.instance.notify(_updatersGroupIds![id]!); 103 + Notifier.instance.read(_updatersGroupIds![id]!);
100 } 104 }
101 105
102 bool containsId(Object id) { 106 bool containsId(Object id) {
@@ -148,44 +152,47 @@ mixin ListNotifierGroupMixin on Listenable { @@ -148,44 +152,47 @@ mixin ListNotifierGroupMixin on Listenable {
148 } 152 }
149 } 153 }
150 154
151 -class NotifierManager {  
152 - NotifierManager._(); 155 +class Notifier {
  156 + Notifier._();
153 157
154 - static NotifierManager? _instance; 158 + static Notifier? _instance;
  159 + static Notifier get instance => _instance ??= Notifier._();
155 160
156 - static NotifierManager get instance => _instance ??= NotifierManager._(); 161 + NotifyData? _notifyData;
157 162
158 - GetStateUpdate? _setter;  
159 - List<VoidCallback>? _remove;  
160 -  
161 - void reportAdd(VoidCallback listener) {  
162 - _remove?.add(listener); 163 + void add(VoidCallback listener) {
  164 + _notifyData?.disposers.add(listener);
163 } 165 }
164 166
165 - void notify(ListNotifierSingleMixin _updaters) {  
166 - final listener = _setter;  
167 - if (listener != null) {  
168 - if (!_updaters.containsListener(listener)) {  
169 - _updaters.addListener(listener);  
170 - reportAdd(() => _updaters.removeListener(listener));  
171 - } 167 + void read(ListNotifierSingleMixin _updaters) {
  168 + final listener = _notifyData?.updater;
  169 + if (listener != null && !_updaters.containsListener(listener)) {
  170 + _updaters.addListener(listener);
  171 + add(() => _updaters.removeListener(listener));
172 } 172 }
173 } 173 }
174 174
175 - T exchange<T>(List<VoidCallback> disposers, GetStateUpdate setState,  
176 - T Function() builder) {  
177 - _remove = disposers;  
178 - _setter = setState; 175 + T append<T>(NotifyData data, T Function() builder) {
  176 + _notifyData = data;
179 final result = builder(); 177 final result = builder();
180 - if (disposers.isEmpty) { 178 + if (data.disposers.isEmpty && data.throwException) {
181 throw ObxError(); 179 throw ObxError();
182 } 180 }
183 - _remove = null;  
184 - _setter = null; 181 + _notifyData = data;
185 return result; 182 return result;
186 } 183 }
187 } 184 }
188 185
  186 +class NotifyData {
  187 + const NotifyData(
  188 + {required this.updater,
  189 + required this.disposers,
  190 + this.throwException = true});
  191 + final GetStateUpdate updater;
  192 + final List<VoidCallback> disposers;
  193 + final bool throwException;
  194 +}
  195 +
189 class ObxError { 196 class ObxError {
190 const ObxError(); 197 const ObxError();
191 @override 198 @override
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 2
3 -import '../../get_state_manager.dart'; 3 +import '../rx_flutter/rx_obx_widget.dart';
  4 +import 'get_controllers.dart';
  5 +import 'get_state.dart';
4 6
5 class MixinBuilder<T extends GetxController> extends StatelessWidget { 7 class MixinBuilder<T extends GetxController> extends StatelessWidget {
6 @required 8 @required
@@ -11,7 +13,7 @@ class MixinBuilder<T extends GetxController> extends StatelessWidget { @@ -11,7 +13,7 @@ class MixinBuilder<T extends GetxController> extends StatelessWidget {
11 final void Function(BindElement<T> state)? initState, 13 final void Function(BindElement<T> state)? initState,
12 dispose, 14 dispose,
13 didChangeDependencies; 15 didChangeDependencies;
14 - final void Function(BindWrapper<T> oldWidget, BindElement<T> state)? 16 + final void Function(Binder<T> oldWidget, BindElement<T> state)?
15 didUpdateWidget; 17 didUpdateWidget;
16 final T? init; 18 final T? init;
17 19
@@ -45,7 +45,6 @@ class _ValueBuilderState<T> extends State<ValueBuilder<T>> { @@ -45,7 +45,6 @@ class _ValueBuilderState<T> extends State<ValueBuilder<T>> {
45 T value; 45 T value;
46 _ValueBuilderState(this.value); 46 _ValueBuilderState(this.value);
47 47
48 -  
49 @override 48 @override
50 Widget build(BuildContext context) => widget.builder(value, updater); 49 Widget build(BuildContext context) => widget.builder(value, updater);
51 50
@@ -92,17 +91,27 @@ abstract class ObxStatelessWidget extends StatelessWidget { @@ -92,17 +91,27 @@ abstract class ObxStatelessWidget extends StatelessWidget {
92 91
93 /// a Component that can track changes in a reactive variable 92 /// a Component that can track changes in a reactive variable
94 mixin ObserverComponent on ComponentElement { 93 mixin ObserverComponent on ComponentElement {
95 - final disposers = <Disposer>[]; 94 + List<Disposer>? disposers = <Disposer>[];
  95 +
  96 + void getUpdate() {
  97 + if (disposers != null) {
  98 + markNeedsBuild();
  99 + }
  100 + }
96 101
97 @override 102 @override
98 - Widget build() =>  
99 - NotifierManager.instance.exchange(disposers, markNeedsBuild, super.build); 103 + Widget build() {
  104 + return Notifier.instance.append(
  105 + NotifyData(disposers: disposers!, updater: getUpdate), super.build);
  106 + }
100 107
101 @override 108 @override
102 void unmount() { 109 void unmount() {
103 super.unmount(); 110 super.unmount();
104 - for (final disposer in disposers) { 111 + for (final disposer in disposers!) {
105 disposer(); 112 disposer();
106 } 113 }
  114 + disposers!.clear();
  115 + disposers = null;
107 } 116 }
108 } 117 }
1 import 'package:collection/collection.dart'; 1 import 'package:collection/collection.dart';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 3
4 -extension ContextExtensionss on BuildContext { 4 +extension ContextExt on BuildContext {
5 /// The same of [MediaQuery.of(context).size] 5 /// The same of [MediaQuery.of(context).size]
6 Size get mediaQuerySize => MediaQuery.of(this).size; 6 Size get mediaQuerySize => MediaQuery.of(this).size;
7 7
@@ -105,8 +105,8 @@ extension ContextExtensionss on BuildContext { @@ -105,8 +105,8 @@ extension ContextExtensionss on BuildContext {
105 /// True if the width is higher than 600p 105 /// True if the width is higher than 600p
106 bool get isPhoneOrWider => width >= 600; 106 bool get isPhoneOrWider => width >= 600;
107 107
108 - /// same as [isPhoneOrLess]  
109 - bool get isPhone => isPhoneOrLess; 108 + /// True if the shortestSide is smaller than 600p
  109 + bool get isPhone => (mediaQueryShortestSide < 600);
110 110
111 /// True if the width is smaller than 600p 111 /// True if the width is smaller than 600p
112 bool get isSmallTabletOrLess => width <= 600; 112 bool get isSmallTabletOrLess => width <= 600;
@@ -114,8 +114,11 @@ extension ContextExtensionss on BuildContext { @@ -114,8 +114,11 @@ extension ContextExtensionss on BuildContext {
114 /// True if the width is higher than 600p 114 /// True if the width is higher than 600p
115 bool get isSmallTabletOrWider => width >= 600; 115 bool get isSmallTabletOrWider => width >= 600;
116 116
117 - /// same as [isSmallTabletOrLess]  
118 - bool get isSmallTablet => isSmallTabletOrLess; 117 + /// True if the shortestSide is largest than 600p
  118 + bool get isSmallTablet => (mediaQueryShortestSide >= 600);
  119 +
  120 + /// True if the shortestSide is largest than 720p
  121 + bool get isLargeTablet => (mediaQueryShortestSide >= 720);
119 122
120 /// True if the width is smaller than 720p 123 /// True if the width is smaller than 720p
121 bool get isLargeTabletOrLess => width <= 720; 124 bool get isLargeTabletOrLess => width <= 720;
@@ -123,11 +126,8 @@ extension ContextExtensionss on BuildContext { @@ -123,11 +126,8 @@ extension ContextExtensionss on BuildContext {
123 /// True if the width is higher than 720p 126 /// True if the width is higher than 720p
124 bool get isLargeTabletOrWider => width >= 720; 127 bool get isLargeTabletOrWider => width >= 720;
125 128
126 - /// same as [isLargeTabletOrLess]  
127 - bool get isLargeTablet => isLargeTabletOrLess;  
128 -  
129 /// True if the current device is Tablet 129 /// True if the current device is Tablet
130 - bool get isTablet => isSmallTablet; 130 + bool get isTablet => isSmallTablet || isLargeTablet;
131 131
132 /// True if the width is smaller than 1200p 132 /// True if the width is smaller than 1200p
133 bool get isDesktopOrLess => width <= 1200; 133 bool get isDesktopOrLess => width <= 1200;
1 import '../get_utils/get_utils.dart'; 1 import '../get_utils/get_utils.dart';
2 2
3 extension GetDynamicUtils on dynamic { 3 extension GetDynamicUtils on dynamic {
4 - @Deprecated('isNull is deprecated and cannot be used, use "==" operator')  
5 - bool get isNull => GetUtils.isNull(this);  
6 -  
7 bool? get isBlank => GetUtils.isBlank(this); 4 bool? get isBlank => GetUtils.isBlank(this);
8 5
9 @Deprecated( 6 @Deprecated(
1 import '../get_utils/get_utils.dart'; 1 import '../get_utils/get_utils.dart';
2 2
3 extension GetStringUtils on String { 3 extension GetStringUtils on String {
  4 + /// Discover if the String is a valid number
4 bool get isNum => GetUtils.isNum(this); 5 bool get isNum => GetUtils.isNum(this);
5 6
  7 + /// Discover if the String is numeric only
6 bool get isNumericOnly => GetUtils.isNumericOnly(this); 8 bool get isNumericOnly => GetUtils.isNumericOnly(this);
7 9
  10 + String numericOnly({bool firstWordOnly = false}) =>
  11 + GetUtils.numericOnly(this, firstWordOnly: firstWordOnly);
  12 +
  13 + /// Discover if the String is alphanumeric only
8 bool get isAlphabetOnly => GetUtils.isAlphabetOnly(this); 14 bool get isAlphabetOnly => GetUtils.isAlphabetOnly(this);
9 15
  16 + /// Discover if the String is a boolean
10 bool get isBool => GetUtils.isBool(this); 17 bool get isBool => GetUtils.isBool(this);
11 18
  19 + /// Discover if the String is a vector
12 bool get isVectorFileName => GetUtils.isVector(this); 20 bool get isVectorFileName => GetUtils.isVector(this);
13 21
  22 + /// Discover if the String is a ImageFileName
14 bool get isImageFileName => GetUtils.isImage(this); 23 bool get isImageFileName => GetUtils.isImage(this);
15 24
  25 + /// Discover if the String is a AudioFileName
16 bool get isAudioFileName => GetUtils.isAudio(this); 26 bool get isAudioFileName => GetUtils.isAudio(this);
17 27
  28 + /// Discover if the String is a VideoFileName
18 bool get isVideoFileName => GetUtils.isVideo(this); 29 bool get isVideoFileName => GetUtils.isVideo(this);
19 30
  31 + /// Discover if the String is a TxtFileName
20 bool get isTxtFileName => GetUtils.isTxt(this); 32 bool get isTxtFileName => GetUtils.isTxt(this);
21 33
  34 + /// Discover if the String is a Document Word
22 bool get isDocumentFileName => GetUtils.isWord(this); 35 bool get isDocumentFileName => GetUtils.isWord(this);
23 36
  37 + /// Discover if the String is a Document Excel
24 bool get isExcelFileName => GetUtils.isExcel(this); 38 bool get isExcelFileName => GetUtils.isExcel(this);
25 39
  40 + /// Discover if the String is a Document Powerpoint
26 bool get isPPTFileName => GetUtils.isPPT(this); 41 bool get isPPTFileName => GetUtils.isPPT(this);
27 42
  43 + /// Discover if the String is a APK File
28 bool get isAPKFileName => GetUtils.isAPK(this); 44 bool get isAPKFileName => GetUtils.isAPK(this);
29 45
  46 + /// Discover if the String is a PDF file
30 bool get isPDFFileName => GetUtils.isPDF(this); 47 bool get isPDFFileName => GetUtils.isPDF(this);
31 48
  49 + /// Discover if the String is a HTML file
32 bool get isHTMLFileName => GetUtils.isHTML(this); 50 bool get isHTMLFileName => GetUtils.isHTML(this);
33 51
  52 + /// Discover if the String is a URL file
34 bool get isURL => GetUtils.isURL(this); 53 bool get isURL => GetUtils.isURL(this);
35 54
  55 + /// Discover if the String is a Email
36 bool get isEmail => GetUtils.isEmail(this); 56 bool get isEmail => GetUtils.isEmail(this);
37 57
  58 + /// Discover if the String is a Phone Number
38 bool get isPhoneNumber => GetUtils.isPhoneNumber(this); 59 bool get isPhoneNumber => GetUtils.isPhoneNumber(this);
39 60
  61 + /// Discover if the String is a DateTime
40 bool get isDateTime => GetUtils.isDateTime(this); 62 bool get isDateTime => GetUtils.isDateTime(this);
41 63
  64 + /// Discover if the String is a MD5 Hash
42 bool get isMD5 => GetUtils.isMD5(this); 65 bool get isMD5 => GetUtils.isMD5(this);
43 66
  67 + /// Discover if the String is a SHA1 Hash
44 bool get isSHA1 => GetUtils.isSHA1(this); 68 bool get isSHA1 => GetUtils.isSHA1(this);
45 69
  70 + /// Discover if the String is a SHA256 Hash
46 bool get isSHA256 => GetUtils.isSHA256(this); 71 bool get isSHA256 => GetUtils.isSHA256(this);
47 72
  73 + /// Discover if the String is a bynary value
48 bool get isBinary => GetUtils.isBinary(this); 74 bool get isBinary => GetUtils.isBinary(this);
49 75
  76 + /// Discover if the String is a ipv4
50 bool get isIPv4 => GetUtils.isIPv4(this); 77 bool get isIPv4 => GetUtils.isIPv4(this);
51 78
52 bool get isIPv6 => GetUtils.isIPv6(this); 79 bool get isIPv6 => GetUtils.isIPv6(this);
53 80
  81 + /// Discover if the String is a Hexadecimal
54 bool get isHexadecimal => GetUtils.isHexadecimal(this); 82 bool get isHexadecimal => GetUtils.isHexadecimal(this);
55 83
  84 + /// Discover if the String is a palindrom
56 bool get isPalindrom => GetUtils.isPalindrom(this); 85 bool get isPalindrom => GetUtils.isPalindrom(this);
57 86
  87 + /// Discover if the String is a passport number
58 bool get isPassport => GetUtils.isPassport(this); 88 bool get isPassport => GetUtils.isPassport(this);
59 89
  90 + /// Discover if the String is a currency
60 bool get isCurrency => GetUtils.isCurrency(this); 91 bool get isCurrency => GetUtils.isCurrency(this);
61 92
  93 + /// Discover if the String is a CPF number
62 bool get isCpf => GetUtils.isCpf(this); 94 bool get isCpf => GetUtils.isCpf(this);
63 95
  96 + /// Discover if the String is a CNPJ number
64 bool get isCnpj => GetUtils.isCnpj(this); 97 bool get isCnpj => GetUtils.isCnpj(this);
65 98
  99 + /// Discover if the String is a case insensitive
66 bool isCaseInsensitiveContains(String b) => 100 bool isCaseInsensitiveContains(String b) =>
67 GetUtils.isCaseInsensitiveContains(this, b); 101 GetUtils.isCaseInsensitiveContains(this, b);
68 102
  103 + /// Discover if the String is a case sensitive and contains any value
69 bool isCaseInsensitiveContainsAny(String b) => 104 bool isCaseInsensitiveContainsAny(String b) =>
70 GetUtils.isCaseInsensitiveContainsAny(this, b); 105 GetUtils.isCaseInsensitiveContainsAny(this, b);
71 106
  107 + /// capitalize the String
72 String? get capitalize => GetUtils.capitalize(this); 108 String? get capitalize => GetUtils.capitalize(this);
73 109
  110 + /// Capitalize the first letter of the String
74 String? get capitalizeFirst => GetUtils.capitalizeFirst(this); 111 String? get capitalizeFirst => GetUtils.capitalizeFirst(this);
75 112
  113 + /// remove all whitespace from the String
76 String get removeAllWhitespace => GetUtils.removeAllWhitespace(this); 114 String get removeAllWhitespace => GetUtils.removeAllWhitespace(this);
77 115
  116 + /// converter the String
78 String? get camelCase => GetUtils.camelCase(this); 117 String? get camelCase => GetUtils.camelCase(this);
79 118
  119 + /// Discover if the String is a valid URL
80 String? get paramCase => GetUtils.paramCase(this); 120 String? get paramCase => GetUtils.paramCase(this);
81 121
82 - String numericOnly({bool firstWordOnly = false}) =>  
83 - GetUtils.numericOnly(this, firstWordOnly: firstWordOnly);  
84 - 122 + /// add segments to the String
85 String createPath([Iterable? segments]) { 123 String createPath([Iterable? segments]) {
86 final path = startsWith('/') ? this : '/$this'; 124 final path = startsWith('/') ? this : '/$this';
87 return GetUtils.createPath(path, segments); 125 return GetUtils.createPath(path, segments);
  1 +import 'package:flutter/material.dart';
  2 +
  3 +class OtimizedListView<T> extends StatelessWidget {
  4 + final List<T> list;
  5 + final Axis scrollDirection;
  6 + final bool reverse;
  7 + final ScrollController? controller;
  8 + final bool? primary;
  9 + final ScrollPhysics? physics;
  10 + final bool shrinkWrap;
  11 + final Widget onEmpty;
  12 + final int lenght;
  13 + final Widget Function(BuildContext context, ValueKey key, T item) builder;
  14 + const OtimizedListView({
  15 + Key? key,
  16 + required this.list,
  17 + required this.builder,
  18 + this.scrollDirection = Axis.vertical,
  19 + this.reverse = false,
  20 + this.controller,
  21 + this.primary,
  22 + this.physics,
  23 + this.onEmpty = const SizedBox.shrink(),
  24 + this.shrinkWrap = false,
  25 + }) : lenght = list.length,
  26 + super(key: key);
  27 + @override
  28 + Widget build(BuildContext context) {
  29 + if (list.isEmpty) return onEmpty;
  30 +
  31 + return CustomScrollView(
  32 + controller: controller,
  33 + reverse: reverse,
  34 + scrollDirection: scrollDirection,
  35 + primary: primary,
  36 + physics: physics,
  37 + shrinkWrap: shrinkWrap,
  38 + slivers: <Widget>[
  39 + SliverList(
  40 + delegate: SliverChildBuilderDelegate(
  41 + (context, i) {
  42 + final item = list[i];
  43 + final key = ValueKey(item);
  44 + return builder(context, key, item);
  45 + },
  46 + childCount: list.length,
  47 + addAutomaticKeepAlives: true,
  48 + findChildIndexCallback: (key) {
  49 + return list.indexWhere((m) => m == (key as ValueKey<T>).value);
  50 + },
  51 + ),
  52 + ),
  53 + ],
  54 + );
  55 + }
  56 +}
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:flutter_test/flutter_test.dart'; 2 import 'package:flutter_test/flutter_test.dart';
3 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
  4 +import 'package:get/get_state_manager/src/simple/mixin_builder.dart';
4 5
5 void main() { 6 void main() {
6 - testWidgets("MixinBuilder smoke test", (tester) async { 7 + testWidgets("MixinBuilder with reactive and not reactive", (tester) async {
7 await tester.pumpWidget( 8 await tester.pumpWidget(
8 MaterialApp( 9 MaterialApp(
9 home: MixinBuilder<Controller>( 10 home: MixinBuilder<Controller>(
@@ -35,6 +36,10 @@ void main() { @@ -35,6 +36,10 @@ void main() {
35 TextButton( 36 TextButton(
36 child: Text("increment"), 37 child: Text("increment"),
37 onPressed: () => controller.increment(), 38 onPressed: () => controller.increment(),
  39 + ),
  40 + TextButton(
  41 + child: Text("increment2"),
  42 + onPressed: () => controller.increment2(),
38 ) 43 )
39 ], 44 ],
40 ); 45 );
@@ -62,6 +67,12 @@ void main() { @@ -62,6 +67,12 @@ void main() {
62 await tester.pump(); 67 await tester.pump();
63 68
64 expect(find.text("Count: 2"), findsOneWidget); 69 expect(find.text("Count: 2"), findsOneWidget);
  70 +
  71 + await tester.tap(find.text('increment2'));
  72 +
  73 + await tester.pump();
  74 +
  75 + expect(find.text("Count2: 1"), findsOneWidget);
65 }); 76 });
66 77
67 // testWidgets( 78 // testWidgets(