Committed by
GitHub
Merge pull request #14 from jonataslaw/master
Update
Showing
23 changed files
with
230 additions
and
168 deletions
@@ -3,12 +3,11 @@ name: build | @@ -3,12 +3,11 @@ name: build | ||
3 | # Trigger the workflow on push or pull request | 3 | # Trigger the workflow on push or pull request |
4 | on: | 4 | on: |
5 | push: | 5 | push: |
6 | - branches: [ master ] | 6 | + branches: [master] |
7 | pull_request: | 7 | pull_request: |
8 | - branches: [ master ] | 8 | + branches: [master] |
9 | #A workflow run is made up of one or more jobs. Jobs run in parallel by default. | 9 | #A workflow run is made up of one or more jobs. Jobs run in parallel by default. |
10 | jobs: | 10 | jobs: |
11 | - | ||
12 | test: | 11 | test: |
13 | #The type of machine to run the job on. [windows,macos, ubuntu , self-hosted] | 12 | #The type of machine to run the job on. [windows,macos, ubuntu , self-hosted] |
14 | defaults: | 13 | defaults: |
@@ -24,8 +23,8 @@ jobs: | @@ -24,8 +23,8 @@ jobs: | ||
24 | # https://github.com/marketplace/actions/flutter-action | 23 | # https://github.com/marketplace/actions/flutter-action |
25 | - uses: subosito/flutter-action@v1 | 24 | - uses: subosito/flutter-action@v1 |
26 | with: | 25 | with: |
27 | - flutter-version: '1.20.4' | ||
28 | - channel: 'stable' | 26 | + flutter-version: "1.22.2" |
27 | + channel: "stable" | ||
29 | - run: flutter pub get | 28 | - run: flutter pub get |
30 | #- run: flutter analyze | 29 | #- run: flutter analyze |
31 | # run flutter widgets tests and unit tests | 30 | # run flutter widgets tests and unit tests |
@@ -33,4 +32,3 @@ jobs: | @@ -33,4 +32,3 @@ jobs: | ||
33 | # Upload coverage reports to Codecov | 32 | # Upload coverage reports to Codecov |
34 | # https://github.com/marketplace/actions/codecov | 33 | # https://github.com/marketplace/actions/codecov |
35 | - uses: codecov/codecov-action@v1.0.7 | 34 | - uses: codecov/codecov-action@v1.0.7 |
36 | - |
@@ -19,7 +19,10 @@ class HomeController extends GetxController { | @@ -19,7 +19,10 @@ class HomeController extends GetxController { | ||
19 | 19 | ||
20 | /// When the controller is initialized, make the http request | 20 | /// When the controller is initialized, make the http request |
21 | @override | 21 | @override |
22 | - void onInit() => fetchDataFromApi(); | 22 | + void onInit() { |
23 | + super.onInit(); | ||
24 | + fetchDataFromApi(); | ||
25 | + } | ||
23 | 26 | ||
24 | /// fetch cases from Api | 27 | /// fetch cases from Api |
25 | Future<void> fetchDataFromApi() async { | 28 | Future<void> fetchDataFromApi() async { |
@@ -170,7 +170,9 @@ class Controller extends GetxController { | @@ -170,7 +170,9 @@ class Controller extends GetxController { | ||
170 | super.onReady(); | 170 | super.onReady(); |
171 | } | 171 | } |
172 | 172 | ||
173 | + @override | ||
173 | void onClose() { | 174 | void onClose() { |
175 | + super.onClose(); | ||
174 | print('onClose'); | 176 | print('onClose'); |
175 | } | 177 | } |
176 | } | 178 | } |
lib/get_core/src/typedefs.dart
0 → 100644
1 | +typedef ValueUpdater<T> = T Function(); |
1 | +import 'package:meta/meta.dart'; | ||
2 | +import '../../get_core/get_core.dart'; | ||
3 | + | ||
1 | /// Special callable class to keep the contract of a regular method, and avoid | 4 | /// Special callable class to keep the contract of a regular method, and avoid |
2 | /// overrides if you extend the class that uses it, as Dart has no final | 5 | /// overrides if you extend the class that uses it, as Dart has no final |
3 | /// methods. | 6 | /// methods. |
4 | /// Used in [DisposableInterface] to avoid the danger of overriding onStart. | 7 | /// Used in [DisposableInterface] to avoid the danger of overriding onStart. |
5 | -/// | ||
6 | class _InternalFinalCallback<T> { | 8 | class _InternalFinalCallback<T> { |
7 | - T Function() callback; | 9 | + ValueUpdater<T> _callback; |
8 | 10 | ||
9 | - _InternalFinalCallback(); | 11 | + _InternalFinalCallback({ValueUpdater<T> callback}) : _callback = callback; |
10 | 12 | ||
11 | - T call() => callback.call(); | 13 | + T call() => _callback.call(); |
12 | } | 14 | } |
13 | 15 | ||
16 | +/// The [GetLifeCycle] | ||
17 | +/// | ||
18 | +/// ```dart | ||
19 | +/// class SomeController with GetLifeCycle { | ||
20 | +/// SomeController() { | ||
21 | +/// initLifeCycle(); | ||
22 | +/// } | ||
23 | +/// } | ||
24 | +/// ``` | ||
14 | mixin GetLifeCycle { | 25 | mixin GetLifeCycle { |
26 | + /// The `initLifeCycle` works as a constructor for the [GetLifeCycle] | ||
27 | + /// | ||
28 | + /// This method must be invoked in the constructor of the implementation | ||
29 | + void initLifeCycle() { | ||
30 | + onStart._callback = _onStart; | ||
31 | + onDelete._callback = _onDelete; | ||
32 | + } | ||
33 | + | ||
15 | /// Called at the exact moment the widget is allocated in memory. | 34 | /// Called at the exact moment the widget is allocated in memory. |
16 | /// It uses an internal "callable" type, to avoid any @overrides in subclases. | 35 | /// It uses an internal "callable" type, to avoid any @overrides in subclases. |
17 | /// This method should be internal and is required to define the | 36 | /// This method should be internal and is required to define the |
18 | /// lifetime cycle of the subclass. | 37 | /// lifetime cycle of the subclass. |
19 | final onStart = _InternalFinalCallback<void>(); | 38 | final onStart = _InternalFinalCallback<void>(); |
20 | 39 | ||
40 | + /// Internal callback that starts the cycle of this controller. | ||
21 | final onDelete = _InternalFinalCallback<void>(); | 41 | final onDelete = _InternalFinalCallback<void>(); |
22 | 42 | ||
23 | /// Called immediately after the widget is allocated in memory. | 43 | /// Called immediately after the widget is allocated in memory. |
24 | /// You might use this to initialize something for the controller. | 44 | /// You might use this to initialize something for the controller. |
45 | + @mustCallSuper | ||
25 | void onInit() {} | 46 | void onInit() {} |
26 | 47 | ||
27 | /// Called 1 frame after onInit(). It is the perfect place to enter | 48 | /// Called 1 frame after onInit(). It is the perfect place to enter |
28 | /// navigation events, like snackbar, dialogs, or a new route, or | 49 | /// navigation events, like snackbar, dialogs, or a new route, or |
29 | /// async request. | 50 | /// async request. |
51 | + @mustCallSuper | ||
30 | void onReady() {} | 52 | void onReady() {} |
31 | 53 | ||
32 | /// Called before [onDelete] method. [onClose] might be used to | 54 | /// Called before [onDelete] method. [onClose] might be used to |
@@ -35,7 +57,32 @@ mixin GetLifeCycle { | @@ -35,7 +57,32 @@ mixin GetLifeCycle { | ||
35 | /// Or dispose objects that can potentially create some memory leaks, | 57 | /// Or dispose objects that can potentially create some memory leaks, |
36 | /// like TextEditingControllers, AnimationControllers. | 58 | /// like TextEditingControllers, AnimationControllers. |
37 | /// Might be useful as well to persist some data on disk. | 59 | /// Might be useful as well to persist some data on disk. |
60 | + @mustCallSuper | ||
38 | void onClose() {} | 61 | void onClose() {} |
62 | + | ||
63 | + bool _initialized = false; | ||
64 | + | ||
65 | + /// Checks whether the controller has already been initialized. | ||
66 | + bool get initialized => _initialized; | ||
67 | + | ||
68 | + // Internal callback that starts the cycle of this controller. | ||
69 | + void _onStart() { | ||
70 | + if (_initialized) return; | ||
71 | + onInit(); | ||
72 | + _initialized = true; | ||
73 | + } | ||
74 | + | ||
75 | + bool _isClosed = false; | ||
76 | + | ||
77 | + /// Checks whether the controller has already been closed. | ||
78 | + bool get isClosed => _isClosed; | ||
79 | + | ||
80 | + // Internal callback that starts the cycle of this controller. | ||
81 | + void _onDelete() { | ||
82 | + if (_isClosed) return; | ||
83 | + _isClosed = true; | ||
84 | + onClose(); | ||
85 | + } | ||
39 | } | 86 | } |
40 | 87 | ||
41 | /// Allow track difference between GetxServices and GetxControllers | 88 | /// Allow track difference between GetxServices and GetxControllers |
@@ -5,7 +5,6 @@ export 'src/extension_navigation.dart'; | @@ -5,7 +5,6 @@ export 'src/extension_navigation.dart'; | ||
5 | export 'src/root/root_widget.dart'; | 5 | export 'src/root/root_widget.dart'; |
6 | export 'src/routes/custom_transition.dart'; | 6 | export 'src/routes/custom_transition.dart'; |
7 | export 'src/routes/default_route.dart'; | 7 | export 'src/routes/default_route.dart'; |
8 | -export 'src/routes/default_route.dart'; | ||
9 | export 'src/routes/get_route.dart'; | 8 | export 'src/routes/get_route.dart'; |
10 | export 'src/routes/observers/route_observer.dart'; | 9 | export 'src/routes/observers/route_observer.dart'; |
11 | export 'src/routes/transitions_type.dart'; | 10 | export 'src/routes/transitions_type.dart'; |
@@ -104,7 +104,7 @@ extension ExtensionSnackbar on GetInterface { | @@ -104,7 +104,7 @@ extension ExtensionSnackbar on GetInterface { | ||
104 | return key?.currentState?.push(SnackRoute<T>(snack: snackbar)); | 104 | return key?.currentState?.push(SnackRoute<T>(snack: snackbar)); |
105 | } | 105 | } |
106 | 106 | ||
107 | - void snackbar( | 107 | + void snackbar<T>( |
108 | String title, | 108 | String title, |
109 | String message, { | 109 | String message, { |
110 | Color colorText, | 110 | Color colorText, |
@@ -199,11 +199,11 @@ extension ExtensionSnackbar on GetInterface { | @@ -199,11 +199,11 @@ extension ExtensionSnackbar on GetInterface { | ||
199 | userInputForm: userInputForm); | 199 | userInputForm: userInputForm); |
200 | 200 | ||
201 | if (instantInit) { | 201 | if (instantInit) { |
202 | - showSnackbar(getBar); | 202 | + showSnackbar<T>(getBar); |
203 | } else { | 203 | } else { |
204 | routing.isSnackbar = true; | 204 | routing.isSnackbar = true; |
205 | SchedulerBinding.instance.addPostFrameCallback((_) { | 205 | SchedulerBinding.instance.addPostFrameCallback((_) { |
206 | - showSnackbar(getBar); | 206 | + showSnackbar<T>(getBar); |
207 | }); | 207 | }); |
208 | } | 208 | } |
209 | } | 209 | } |
@@ -220,9 +220,11 @@ extension ExtensionDialog on GetInterface { | @@ -220,9 +220,11 @@ extension ExtensionDialog on GetInterface { | ||
220 | Color barrierColor, | 220 | Color barrierColor, |
221 | bool useSafeArea = true, | 221 | bool useSafeArea = true, |
222 | bool useRootNavigator = true, | 222 | bool useRootNavigator = true, |
223 | - RouteSettings routeSettings, | 223 | + Object arguments, |
224 | Duration transitionDuration, | 224 | Duration transitionDuration, |
225 | Curve transitionCurve, | 225 | Curve transitionCurve, |
226 | + String name, | ||
227 | + RouteSettings routeSettings, | ||
226 | }) { | 228 | }) { |
227 | assert(widget != null); | 229 | assert(widget != null); |
228 | assert(barrierDismissible != null); | 230 | assert(barrierDismissible != null); |
@@ -231,7 +233,7 @@ extension ExtensionDialog on GetInterface { | @@ -231,7 +233,7 @@ extension ExtensionDialog on GetInterface { | ||
231 | assert(debugCheckHasMaterialLocalizations(context)); | 233 | assert(debugCheckHasMaterialLocalizations(context)); |
232 | 234 | ||
233 | final theme = Theme.of(context, shadowThemeOnly: true); | 235 | final theme = Theme.of(context, shadowThemeOnly: true); |
234 | - return generalDialog( | 236 | + return generalDialog<T>( |
235 | pageBuilder: (buildContext, animation, secondaryAnimation) { | 237 | pageBuilder: (buildContext, animation, secondaryAnimation) { |
236 | final pageChild = widget; | 238 | final pageChild = widget; |
237 | Widget dialog = Builder(builder: (context) { | 239 | Widget dialog = Builder(builder: (context) { |
@@ -258,7 +260,8 @@ extension ExtensionDialog on GetInterface { | @@ -258,7 +260,8 @@ extension ExtensionDialog on GetInterface { | ||
258 | ); | 260 | ); |
259 | }, | 261 | }, |
260 | useRootNavigator: useRootNavigator, | 262 | useRootNavigator: useRootNavigator, |
261 | - routeSettings: routeSettings, | 263 | + routeSettings: |
264 | + routeSettings ?? RouteSettings(arguments: arguments, name: name), | ||
262 | ); | 265 | ); |
263 | } | 266 | } |
264 | 267 | ||
@@ -360,7 +363,7 @@ extension ExtensionDialog on GetInterface { | @@ -360,7 +363,7 @@ extension ExtensionDialog on GetInterface { | ||
360 | } | 363 | } |
361 | } | 364 | } |
362 | 365 | ||
363 | - return dialog( | 366 | + return dialog<T>( |
364 | AlertDialog( | 367 | AlertDialog( |
365 | titlePadding: EdgeInsets.all(8), | 368 | titlePadding: EdgeInsets.all(8), |
366 | contentPadding: EdgeInsets.all(8), | 369 | contentPadding: EdgeInsets.all(8), |
@@ -484,8 +487,8 @@ extension GetNavigation on GetInterface { | @@ -484,8 +487,8 @@ extension GetNavigation on GetInterface { | ||
484 | if (preventDuplicates && routeName == currentRoute) { | 487 | if (preventDuplicates && routeName == currentRoute) { |
485 | return null; | 488 | return null; |
486 | } | 489 | } |
487 | - return global(id)?.currentState?.push( | ||
488 | - GetPageRoute( | 490 | + return global(id)?.currentState?.push<T>( |
491 | + GetPageRoute<T>( | ||
489 | opaque: opaque ?? true, | 492 | opaque: opaque ?? true, |
490 | page: () => page, | 493 | page: () => page, |
491 | routeName: routeName, | 494 | routeName: routeName, |
@@ -528,7 +531,7 @@ extension GetNavigation on GetInterface { | @@ -528,7 +531,7 @@ extension GetNavigation on GetInterface { | ||
528 | if (preventDuplicates && page == currentRoute) { | 531 | if (preventDuplicates && page == currentRoute) { |
529 | return null; | 532 | return null; |
530 | } | 533 | } |
531 | - return global(id)?.currentState?.pushNamed(page, arguments: arguments); | 534 | + return global(id)?.currentState?.pushNamed<T>(page, arguments: arguments); |
532 | } | 535 | } |
533 | 536 | ||
534 | /// **Navigation.pushReplacementNamed()** shortcut.<br><br> | 537 | /// **Navigation.pushReplacementNamed()** shortcut.<br><br> |
@@ -601,7 +604,7 @@ extension GetNavigation on GetInterface { | @@ -601,7 +604,7 @@ extension GetNavigation on GetInterface { | ||
601 | Future<T> offUntil<T>(Route<T> page, RoutePredicate predicate, {int id}) { | 604 | Future<T> offUntil<T>(Route<T> page, RoutePredicate predicate, {int id}) { |
602 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate | 605 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate |
603 | // when widget don't mounted | 606 | // when widget don't mounted |
604 | - return global(id)?.currentState?.pushAndRemoveUntil(page, predicate); | 607 | + return global(id)?.currentState?.pushAndRemoveUntil<T>(page, predicate); |
605 | } | 608 | } |
606 | 609 | ||
607 | /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br> | 610 | /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br> |
@@ -629,7 +632,7 @@ extension GetNavigation on GetInterface { | @@ -629,7 +632,7 @@ extension GetNavigation on GetInterface { | ||
629 | }) { | 632 | }) { |
630 | return global(id) | 633 | return global(id) |
631 | ?.currentState | 634 | ?.currentState |
632 | - ?.pushNamedAndRemoveUntil(page, predicate, arguments: arguments); | 635 | + ?.pushNamedAndRemoveUntil<T>(page, predicate, arguments: arguments); |
633 | } | 636 | } |
634 | 637 | ||
635 | /// **Navigation.popAndPushNamed()** shortcut.<br><br> | 638 | /// **Navigation.popAndPushNamed()** shortcut.<br><br> |
@@ -690,7 +693,7 @@ extension GetNavigation on GetInterface { | @@ -690,7 +693,7 @@ extension GetNavigation on GetInterface { | ||
690 | dynamic arguments, | 693 | dynamic arguments, |
691 | int id, | 694 | int id, |
692 | }) { | 695 | }) { |
693 | - return global(id)?.currentState?.pushNamedAndRemoveUntil( | 696 | + return global(id)?.currentState?.pushNamedAndRemoveUntil<T>( |
694 | newRouteName, | 697 | newRouteName, |
695 | predicate ?? (_) => false, | 698 | predicate ?? (_) => false, |
696 | arguments: arguments, | 699 | arguments: arguments, |
@@ -717,8 +720,8 @@ extension GetNavigation on GetInterface { | @@ -717,8 +720,8 @@ extension GetNavigation on GetInterface { | ||
717 | /// | 720 | /// |
718 | /// It has the advantage of not needing context, so you can call | 721 | /// It has the advantage of not needing context, so you can call |
719 | /// from your business logic. | 722 | /// from your business logic. |
720 | - void back({ | ||
721 | - dynamic result, | 723 | + void back<T>({ |
724 | + T result, | ||
722 | bool closeOverlays = false, | 725 | bool closeOverlays = false, |
723 | bool canPop = true, | 726 | bool canPop = true, |
724 | int id, | 727 | int id, |
@@ -730,10 +733,10 @@ extension GetNavigation on GetInterface { | @@ -730,10 +733,10 @@ extension GetNavigation on GetInterface { | ||
730 | } | 733 | } |
731 | if (canPop) { | 734 | if (canPop) { |
732 | if (global(id)?.currentState?.canPop() == true) { | 735 | if (global(id)?.currentState?.canPop() == true) { |
733 | - global(id)?.currentState?.pop(result); | 736 | + global(id)?.currentState?.pop<T>(result); |
734 | } | 737 | } |
735 | } else { | 738 | } else { |
736 | - global(id)?.currentState?.pop(result); | 739 | + global(id)?.currentState?.pop<T>(result); |
737 | } | 740 | } |
738 | } | 741 | } |
739 | 742 | ||
@@ -854,8 +857,8 @@ extension GetNavigation on GetInterface { | @@ -854,8 +857,8 @@ extension GetNavigation on GetInterface { | ||
854 | }) { | 857 | }) { |
855 | var routeName = "/${page.runtimeType.toString()}"; | 858 | var routeName = "/${page.runtimeType.toString()}"; |
856 | 859 | ||
857 | - return global(id)?.currentState?.pushAndRemoveUntil( | ||
858 | - GetPageRoute( | 860 | + return global(id)?.currentState?.pushAndRemoveUntil<T>( |
861 | + GetPageRoute<T>( | ||
859 | opaque: opaque ?? true, | 862 | opaque: opaque ?? true, |
860 | popGesture: popGesture ?? defaultPopGesture, | 863 | popGesture: popGesture ?? defaultPopGesture, |
861 | page: () => page, | 864 | page: () => page, |
1 | +import 'package:flutter/material.dart'; | ||
1 | import 'package:flutter/scheduler.dart'; | 2 | import 'package:flutter/scheduler.dart'; |
2 | import '../../../get_instance/src/lifecycle.dart'; | 3 | import '../../../get_instance/src/lifecycle.dart'; |
3 | 4 | ||
@@ -10,45 +11,24 @@ import '../../../get_instance/src/lifecycle.dart'; | @@ -10,45 +11,24 @@ import '../../../get_instance/src/lifecycle.dart'; | ||
10 | abstract class GetxService extends DisposableInterface with GetxServiceMixin {} | 11 | abstract class GetxService extends DisposableInterface with GetxServiceMixin {} |
11 | 12 | ||
12 | abstract class DisposableInterface with GetLifeCycle { | 13 | abstract class DisposableInterface with GetLifeCycle { |
13 | - bool _initialized = false; | ||
14 | - | ||
15 | - /// Checks whether the controller has already been initialized. | ||
16 | - bool get initialized => _initialized; | ||
17 | - | ||
18 | - bool _isClosed = false; | ||
19 | - | ||
20 | - /// Checks whether the controller has already been closed. | ||
21 | - bool get isClosed => _isClosed; | ||
22 | - | ||
23 | DisposableInterface() { | 14 | DisposableInterface() { |
24 | - onStart.callback = _onStart; | ||
25 | - onDelete.callback = _onDelete; | ||
26 | - } | ||
27 | - | ||
28 | - // Internal callback that starts the cycle of this controller. | ||
29 | - void _onStart() { | ||
30 | - if (_initialized) return; | ||
31 | - onInit(); | ||
32 | - _initialized = true; | ||
33 | - SchedulerBinding.instance?.addPostFrameCallback((_) => onReady()); | ||
34 | - } | ||
35 | - | ||
36 | - // Internal callback that starts the cycle of this controller. | ||
37 | - void _onDelete() { | ||
38 | - if (_isClosed) return; | ||
39 | - _isClosed = true; | ||
40 | - onClose(); | 15 | + initLifeCycle(); |
41 | } | 16 | } |
42 | 17 | ||
43 | /// Called immediately after the widget is allocated in memory. | 18 | /// Called immediately after the widget is allocated in memory. |
44 | /// You might use this to initialize something for the controller. | 19 | /// You might use this to initialize something for the controller. |
45 | @override | 20 | @override |
46 | - void onInit() {} | 21 | + @mustCallSuper |
22 | + void onInit() { | ||
23 | + super.onInit(); | ||
24 | + SchedulerBinding.instance?.addPostFrameCallback((_) => onReady()); | ||
25 | + } | ||
47 | 26 | ||
48 | /// Called 1 frame after onInit(). It is the perfect place to enter | 27 | /// Called 1 frame after onInit(). It is the perfect place to enter |
49 | /// navigation events, like snackbar, dialogs, or a new route, or | 28 | /// navigation events, like snackbar, dialogs, or a new route, or |
50 | /// async request. | 29 | /// async request. |
51 | @override | 30 | @override |
31 | + @mustCallSuper | ||
52 | void onReady() {} | 32 | void onReady() {} |
53 | 33 | ||
54 | /// Called before [onDelete] method. [onClose] might be used to | 34 | /// Called before [onDelete] method. [onClose] might be used to |
@@ -38,36 +38,17 @@ typedef Condition = bool Function(); | @@ -38,36 +38,17 @@ typedef Condition = bool Function(); | ||
38 | 38 | ||
39 | abstract class GetNotifier<T> extends Value<T> with GetLifeCycle { | 39 | abstract class GetNotifier<T> extends Value<T> with GetLifeCycle { |
40 | GetNotifier(T initial) : super(initial) { | 40 | GetNotifier(T initial) : super(initial) { |
41 | - onStart.callback = _onStart; | ||
42 | - onDelete.callback = _onDelete; | 41 | + initLifeCycle(); |
43 | _fillEmptyStatus(); | 42 | _fillEmptyStatus(); |
44 | } | 43 | } |
45 | 44 | ||
46 | - bool _initialized = false; | ||
47 | - | ||
48 | - /// Checks whether the controller has already been initialized. | ||
49 | - bool get initialized => _initialized; | ||
50 | - | ||
51 | - bool _isClosed = false; | ||
52 | - | ||
53 | - /// Checks whether the controller has already been closed. | ||
54 | - bool get isClosed => _isClosed; | ||
55 | - | ||
56 | - // Internal callback that starts the cycle of this controller. | ||
57 | - void _onStart() { | ||
58 | - if (_initialized) return; | ||
59 | - onInit(); | ||
60 | - _initialized = true; | 45 | + @override |
46 | + @mustCallSuper | ||
47 | + void onInit() { | ||
48 | + super.onInit(); | ||
61 | SchedulerBinding.instance?.addPostFrameCallback((_) => onReady()); | 49 | SchedulerBinding.instance?.addPostFrameCallback((_) => onReady()); |
62 | } | 50 | } |
63 | 51 | ||
64 | - // Internal callback that starts the cycle of this controller. | ||
65 | - void _onDelete() { | ||
66 | - if (_isClosed) return; | ||
67 | - _isClosed = true; | ||
68 | - onClose(); | ||
69 | - } | ||
70 | - | ||
71 | RxStatus _status; | 52 | RxStatus _status; |
72 | 53 | ||
73 | bool get isNullOrEmpty { | 54 | bool get isNullOrEmpty { |
@@ -4,22 +4,21 @@ import '../../../get_rx/get_rx.dart'; | @@ -4,22 +4,21 @@ import '../../../get_rx/get_rx.dart'; | ||
4 | 4 | ||
5 | typedef WidgetCallback = Widget Function(); | 5 | typedef WidgetCallback = Widget Function(); |
6 | 6 | ||
7 | -/// The simplest reactive widget in GetX. | ||
8 | -/// | ||
9 | -/// Just pass your Rx variable in the root scope of the callback to have it | ||
10 | -/// automatically registered for changes. | 7 | +/// The [ObxWidget] is the base for all GetX reactive widgets |
11 | /// | 8 | /// |
12 | -/// final _name = "GetX".obs; | ||
13 | -/// Obx(() => Text( _name.value )),... ; | ||
14 | -class Obx extends StatefulWidget { | ||
15 | - final WidgetCallback builder; | ||
16 | - | ||
17 | - const Obx(this.builder); | 9 | +/// See also: |
10 | +/// - [Obx] | ||
11 | +/// - [ObxValue] | ||
12 | +abstract class ObxWidget extends StatefulWidget { | ||
13 | + const ObxWidget({Key key}) : super(key: key); | ||
18 | 14 | ||
19 | _ObxState createState() => _ObxState(); | 15 | _ObxState createState() => _ObxState(); |
16 | + | ||
17 | + @protected | ||
18 | + Widget build(); | ||
20 | } | 19 | } |
21 | 20 | ||
22 | -class _ObxState extends State<Obx> { | 21 | +class _ObxState extends State<ObxWidget> { |
23 | RxInterface _observer; | 22 | RxInterface _observer; |
24 | StreamSubscription subs; | 23 | StreamSubscription subs; |
25 | 24 | ||
@@ -43,7 +42,7 @@ class _ObxState extends State<Obx> { | @@ -43,7 +42,7 @@ class _ObxState extends State<Obx> { | ||
43 | Widget get notifyChilds { | 42 | Widget get notifyChilds { |
44 | final observer = getObs; | 43 | final observer = getObs; |
45 | getObs = _observer; | 44 | getObs = _observer; |
46 | - final result = widget.builder(); | 45 | + final result = widget.build(); |
47 | if (!_observer.canUpdate) { | 46 | if (!_observer.canUpdate) { |
48 | throw """ | 47 | throw """ |
49 | [Get] the improper use of a GetX has been detected. | 48 | [Get] the improper use of a GetX has been detected. |
@@ -62,6 +61,22 @@ class _ObxState extends State<Obx> { | @@ -62,6 +61,22 @@ class _ObxState extends State<Obx> { | ||
62 | Widget build(BuildContext context) => notifyChilds; | 61 | Widget build(BuildContext context) => notifyChilds; |
63 | } | 62 | } |
64 | 63 | ||
64 | +/// The simplest reactive widget in GetX. | ||
65 | +/// | ||
66 | +/// Just pass your Rx variable in the root scope of the callback to have it | ||
67 | +/// automatically registered for changes. | ||
68 | +/// | ||
69 | +/// final _name = "GetX".obs; | ||
70 | +/// Obx(() => Text( _name.value )),... ; | ||
71 | +class Obx extends ObxWidget { | ||
72 | + final WidgetCallback builder; | ||
73 | + | ||
74 | + const Obx(this.builder); | ||
75 | + | ||
76 | + @override | ||
77 | + Widget build() => builder(); | ||
78 | +} | ||
79 | + | ||
65 | /// Similar to Obx, but manages a local state. | 80 | /// Similar to Obx, but manages a local state. |
66 | /// Pass the initial data in constructor. | 81 | /// Pass the initial data in constructor. |
67 | /// Useful for simple local states, like toggles, visibility, themes, | 82 | /// Useful for simple local states, like toggles, visibility, themes, |
@@ -76,45 +91,12 @@ class _ObxState extends State<Obx> { | @@ -76,45 +91,12 @@ class _ObxState extends State<Obx> { | ||
76 | 91 | ||
77 | // TODO: change T to a proper Rx interface, that includes the accessor | 92 | // TODO: change T to a proper Rx interface, that includes the accessor |
78 | // for ::value | 93 | // for ::value |
79 | -class ObxValue<T extends RxInterface> extends StatefulWidget { | 94 | +class ObxValue<T extends RxInterface> extends ObxWidget { |
80 | final Widget Function(T) builder; | 95 | final Widget Function(T) builder; |
81 | final T data; | 96 | final T data; |
82 | 97 | ||
83 | const ObxValue(this.builder, this.data, {Key key}) : super(key: key); | 98 | const ObxValue(this.builder, this.data, {Key key}) : super(key: key); |
84 | 99 | ||
85 | - _ObxValueState createState() => _ObxValueState(); | ||
86 | -} | ||
87 | - | ||
88 | -class _ObxValueState extends State<ObxValue> { | ||
89 | - RxInterface _observer; | ||
90 | - StreamSubscription subs; | ||
91 | - | ||
92 | - _ObxValueState() { | ||
93 | - _observer = Rx(); | ||
94 | - } | ||
95 | - | ||
96 | - @override | ||
97 | - void initState() { | ||
98 | - subs = _observer.subject.stream.listen((data) => setState(() {})); | ||
99 | - super.initState(); | ||
100 | - } | ||
101 | - | ||
102 | - @override | ||
103 | - void dispose() { | ||
104 | - subs.cancel(); | ||
105 | - _observer.close(); | ||
106 | - super.dispose(); | ||
107 | - } | ||
108 | - | ||
109 | - Widget get notifyChilds { | ||
110 | - final observer = getObs; | ||
111 | - getObs = _observer; | ||
112 | - // observable is implicity taken from the constructor. | ||
113 | - final result = widget.builder(widget.data); | ||
114 | - getObs = observer; | ||
115 | - return result; | ||
116 | - } | ||
117 | - | ||
118 | @override | 100 | @override |
119 | - Widget build(BuildContext context) => notifyChilds; | 101 | + Widget build() => builder(data); |
120 | } | 102 | } |
@@ -39,17 +39,21 @@ abstract class GetView<T> extends StatelessWidget { | @@ -39,17 +39,21 @@ abstract class GetView<T> extends StatelessWidget { | ||
39 | Widget build(BuildContext context); | 39 | Widget build(BuildContext context); |
40 | } | 40 | } |
41 | 41 | ||
42 | +class _Wrapper<T> { | ||
43 | + T data; | ||
44 | +} | ||
45 | + | ||
42 | abstract class GetWidget<T extends DisposableInterface> | 46 | abstract class GetWidget<T extends DisposableInterface> |
43 | extends StatelessWidget { | 47 | extends StatelessWidget { |
44 | GetWidget({Key key}) : super(key: key); | 48 | GetWidget({Key key}) : super(key: key); |
45 | 49 | ||
46 | - final Set<T> _value = <T>{}; | 50 | + final _value = _Wrapper<T>(); |
47 | 51 | ||
48 | final String tag = null; | 52 | final String tag = null; |
49 | 53 | ||
50 | T get controller { | 54 | T get controller { |
51 | - if (_value.isEmpty) _value.add(GetInstance().find<T>(tag: tag)); | ||
52 | - return _value.first; | 55 | + _value.data ??= GetInstance().find<T>(tag: tag); |
56 | + return _value.data; | ||
53 | } | 57 | } |
54 | 58 | ||
55 | @override | 59 | @override |
@@ -203,8 +203,10 @@ class GetUtils { | @@ -203,8 +203,10 @@ class GetUtils { | ||
203 | r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'); | 203 | r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'); |
204 | 204 | ||
205 | /// Checks if string is phone number. | 205 | /// Checks if string is phone number. |
206 | - static bool isPhoneNumber(String s) => hasMatch(s, | ||
207 | - r'^(0|\+|(\+[0-9]{2,4}|\(\+?[0-9]{2,4}\)) ?)([0-9]*|\d{2,4}-\d{2,4}(-\d{2,4})?)$'); | 206 | + static bool isPhoneNumber(String s) { |
207 | + if (s == null || s.length > 16 || s.length < 9) return false; | ||
208 | + return hasMatch(s, r'^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$'); | ||
209 | + } | ||
208 | 210 | ||
209 | /// Checks if string is DateTime (UTC or Iso8601). | 211 | /// Checks if string is DateTime (UTC or Iso8601). |
210 | static bool isDateTime(String s) => | 212 | static bool isDateTime(String s) => |
@@ -4,11 +4,12 @@ version: 3.13.2 | @@ -4,11 +4,12 @@ version: 3.13.2 | ||
4 | homepage: https://github.com/jonataslaw/getx | 4 | homepage: https://github.com/jonataslaw/getx |
5 | 5 | ||
6 | environment: | 6 | environment: |
7 | - sdk: ">=2.8.0 <3.0.0" | 7 | + sdk: ">=2.10.0 <3.0.0" |
8 | 8 | ||
9 | dependencies: | 9 | dependencies: |
10 | flutter: | 10 | flutter: |
11 | sdk: flutter | 11 | sdk: flutter |
12 | + meta: 1.3.0-nullsafety.3 | ||
12 | 13 | ||
13 | dev_dependencies: | 14 | dev_dependencies: |
14 | flutter_test: | 15 | flutter_test: |
test/benchmarks/benckmark_test.dart
0 → 100644
1 | +import 'dart:async'; | ||
2 | + | ||
3 | +import 'package:flutter/foundation.dart'; | ||
4 | +import 'package:get/state_manager.dart'; | ||
5 | + | ||
6 | +int times = 3; | ||
7 | +int get last => times - 1; | ||
8 | + | ||
9 | +Future<String> valueNotifier() { | ||
10 | + final c = Completer<String>(); | ||
11 | + final value = ValueNotifier<int>(0); | ||
12 | + final timer = Stopwatch(); | ||
13 | + timer.start(); | ||
14 | + | ||
15 | + value.addListener(() { | ||
16 | + if (last == value.value) { | ||
17 | + timer.stop(); | ||
18 | + c.complete("""${value.value} item value notifier | ||
19 | +objs time: ${timer.elapsedMicroseconds}ms"""); | ||
20 | + } | ||
21 | + }); | ||
22 | + | ||
23 | + for (var i = 0; i < times; i++) { | ||
24 | + value.value = i; | ||
25 | + } | ||
26 | + | ||
27 | + return c.future; | ||
28 | +} | ||
29 | + | ||
30 | +Future<String> getValue() { | ||
31 | + final c = Completer<String>(); | ||
32 | + final value = Value<int>(0); | ||
33 | + final timer = Stopwatch(); | ||
34 | + timer.start(); | ||
35 | + | ||
36 | + value.addListener(() { | ||
37 | + if (last == value.value) { | ||
38 | + timer.stop(); | ||
39 | + c.complete("""${value.value} item get value objs | ||
40 | + time: ${timer.elapsedMicroseconds}ms"""); | ||
41 | + } | ||
42 | + }); | ||
43 | + | ||
44 | + for (var i = 0; i < times; i++) { | ||
45 | + value.value = i; | ||
46 | + } | ||
47 | + | ||
48 | + return c.future; | ||
49 | +} | ||
50 | + | ||
51 | +Future<String> getStream() { | ||
52 | + final c = Completer<String>(); | ||
53 | + | ||
54 | + final value = StreamController<int>(); | ||
55 | + final timer = Stopwatch(); | ||
56 | + timer.start(); | ||
57 | + | ||
58 | + value.stream.listen((v) { | ||
59 | + if (last == v) { | ||
60 | + timer.stop(); | ||
61 | + c.complete("$v item stream objs time: ${timer.elapsedMicroseconds}ms"); | ||
62 | + } | ||
63 | + }); | ||
64 | + | ||
65 | + for (var i = 0; i < times; i++) { | ||
66 | + value.add(i); | ||
67 | + } | ||
68 | + | ||
69 | + return c.future; | ||
70 | +} | ||
71 | + | ||
72 | +void main() async { | ||
73 | + print(await getValue()); | ||
74 | + print(await valueNotifier()); | ||
75 | + print(await getStream()); | ||
76 | + times = 30000; | ||
77 | + print(await getValue()); | ||
78 | + print(await valueNotifier()); | ||
79 | + print(await getStream()); | ||
80 | +} | ||
81 | + | ||
82 | +typedef VoidCallback = void Function(); |
@@ -11,29 +11,7 @@ class Mock { | @@ -11,29 +11,7 @@ class Mock { | ||
11 | 11 | ||
12 | class DisposableController with GetLifeCycle { | 12 | class DisposableController with GetLifeCycle { |
13 | DisposableController() { | 13 | DisposableController() { |
14 | - onStart.callback = _onStart; | ||
15 | - onDelete.callback = _onDelete; | ||
16 | - } | ||
17 | - | ||
18 | - // Internal callback that starts the cycle of this controller. | ||
19 | - void _onStart() { | ||
20 | - if (initialized) return; | ||
21 | - onInit(); | ||
22 | - } | ||
23 | - | ||
24 | - // Internal callback that starts the cycle of this controller. | ||
25 | - void _onDelete() { | ||
26 | - if (isClosed) return; | ||
27 | - isClosed = true; | ||
28 | - onClose(); | ||
29 | - } | ||
30 | - | ||
31 | - bool initialized = false; | ||
32 | - | ||
33 | - bool isClosed = false; | ||
34 | - | ||
35 | - void onInit() async { | ||
36 | - initialized = true; | 14 | + initLifeCycle(); |
37 | } | 15 | } |
38 | } | 16 | } |
39 | 17 |
@@ -73,7 +73,6 @@ void main() { | @@ -73,7 +73,6 @@ void main() { | ||
73 | var expected = ''; | 73 | var expected = ''; |
74 | void logFunction(String prefix, dynamic value, String info, | 74 | void logFunction(String prefix, dynamic value, String info, |
75 | {bool isError = false}) { | 75 | {bool isError = false}) { |
76 | - print('algo'); | ||
77 | expected = '$prefix $value $info'.trim(); | 76 | expected = '$prefix $value $info'.trim(); |
78 | } | 77 | } |
79 | 78 |
@@ -239,14 +239,12 @@ void main() { | @@ -239,14 +239,12 @@ void main() { | ||
239 | '(455) 443-8171', | 239 | '(455) 443-8171', |
240 | '(915) 685-8658', | 240 | '(915) 685-8658', |
241 | '(572) 207-1898', | 241 | '(572) 207-1898', |
242 | - | ||
243 | - // TODO those are failing, but they shouldn't | ||
244 | - // '(81) 6 2499-9538', | ||
245 | - // '(31) 32304-4263', | ||
246 | - // '(64) 25242-6375', | ||
247 | - // '(41) 19308-7925', | ||
248 | - // '(67) 61684-0395', | ||
249 | - // '(60) 54706-3569', | 242 | + '(81) 6 2499-9538', |
243 | + '(31) 32304-4263', | ||
244 | + '(64) 25242-6375', | ||
245 | + '(41) 19308-7925', | ||
246 | + '(67) 61684-0395', | ||
247 | + '(60) 54706-3569', | ||
250 | '(31) 33110055', | 248 | '(31) 33110055', |
251 | '(11) 3344-5599', | 249 | '(11) 3344-5599', |
252 | '(31) 977447788', | 250 | '(31) 977447788', |
-
Please register or login to post a comment