Showing
10 changed files
with
140 additions
and
78 deletions
| @@ -21,6 +21,6 @@ | @@ -21,6 +21,6 @@ | ||
| 21 | <key>CFBundleVersion</key> | 21 | <key>CFBundleVersion</key> |
| 22 | <string>1.0</string> | 22 | <string>1.0</string> |
| 23 | <key>MinimumOSVersion</key> | 23 | <key>MinimumOSVersion</key> |
| 24 | - <string>8.0</string> | 24 | + <string>9.0</string> |
| 25 | </dict> | 25 | </dict> |
| 26 | </plist> | 26 | </plist> |
| @@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
| 3 | archiveVersion = 1; | 3 | archiveVersion = 1; |
| 4 | classes = { | 4 | classes = { |
| 5 | }; | 5 | }; |
| 6 | - objectVersion = 46; | 6 | + objectVersion = 50; |
| 7 | objects = { | 7 | objects = { |
| 8 | 8 | ||
| 9 | /* Begin PBXBuildFile section */ | 9 | /* Begin PBXBuildFile section */ |
| @@ -127,7 +127,7 @@ | @@ -127,7 +127,7 @@ | ||
| 127 | 97C146E61CF9000F007C117D /* Project object */ = { | 127 | 97C146E61CF9000F007C117D /* Project object */ = { |
| 128 | isa = PBXProject; | 128 | isa = PBXProject; |
| 129 | attributes = { | 129 | attributes = { |
| 130 | - LastUpgradeCheck = 1020; | 130 | + LastUpgradeCheck = 1300; |
| 131 | ORGANIZATIONNAME = ""; | 131 | ORGANIZATIONNAME = ""; |
| 132 | TargetAttributes = { | 132 | TargetAttributes = { |
| 133 | 97C146ED1CF9000F007C117D = { | 133 | 97C146ED1CF9000F007C117D = { |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | import 'package:get/get.dart'; | 2 | import 'package:get/get.dart'; |
| 3 | 3 | ||
| 4 | -import 'app/routes/app_pages.dart'; | ||
| 5 | -import 'services/auth_service.dart'; | ||
| 6 | - | ||
| 7 | void main() { | 4 | void main() { |
| 8 | runApp( | 5 | runApp( |
| 9 | - GetMaterialApp.router( | ||
| 10 | - title: "Application", | ||
| 11 | - initialBinding: BindingsBuilder( | ||
| 12 | - () { | ||
| 13 | - Get.put(AuthService()); | ||
| 14 | - }, | 6 | + GetMaterialApp( |
| 7 | + home: Home(), | ||
| 15 | ), | 8 | ), |
| 16 | - getPages: AppPages.routes, | ||
| 17 | - // routeInformationParser: GetInformationParser( | ||
| 18 | - // // initialRoute: Routes.HOME, | ||
| 19 | - // ), | ||
| 20 | - // routerDelegate: GetDelegate( | ||
| 21 | - // backButtonPopMode: PopMode.History, | ||
| 22 | - // preventDuplicateHandlingMode: | ||
| 23 | - // PreventDuplicateHandlingMode.ReorderRoutes, | 9 | + ); |
| 10 | +} | ||
| 11 | + | ||
| 12 | +class Controller extends GetxController { | ||
| 13 | + final count = 0.reactive; | ||
| 14 | + void increment() { | ||
| 15 | + count.value++; | ||
| 16 | + update(); | ||
| 17 | + } | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +class Home extends ObxStatelessWidget { | ||
| 21 | + const Home({Key? key}) : super(key: key); | ||
| 22 | + @override | ||
| 23 | + Widget build(BuildContext context) { | ||
| 24 | + final controller = Get.put(Controller()); | ||
| 25 | + return Scaffold( | ||
| 26 | + appBar: AppBar(title: Text("counter")), | ||
| 27 | + body: Center( | ||
| 28 | + child: Column( | ||
| 29 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 30 | + children: [ | ||
| 31 | + SimpleBuilder(builder: (context) { | ||
| 32 | + print('builder'); | ||
| 33 | + return Text( | ||
| 34 | + '${controller.count.value}', | ||
| 35 | + style: TextStyle(fontSize: 30), | ||
| 36 | + ); | ||
| 37 | + }), | ||
| 38 | + // ElevatedButton( | ||
| 39 | + // child: Text('Next Route'), | ||
| 40 | + // onPressed: () { | ||
| 41 | + // Get.to(() => Second()); | ||
| 42 | + // }, | ||
| 24 | // ), | 43 | // ), |
| 44 | + ], | ||
| 45 | + ), | ||
| 46 | + ), | ||
| 47 | + floatingActionButton: FloatingActionButton( | ||
| 48 | + child: Icon(Icons.add), | ||
| 49 | + onPressed: controller.increment, | ||
| 25 | ), | 50 | ), |
| 26 | ); | 51 | ); |
| 52 | + } | ||
| 27 | } | 53 | } |
| @@ -6,7 +6,8 @@ import 'package:flutter/material.dart'; | @@ -6,7 +6,8 @@ import 'package:flutter/material.dart'; | ||
| 6 | import '../../../get.dart'; | 6 | import '../../../get.dart'; |
| 7 | import '../../../get_state_manager/src/simple/list_notifier.dart'; | 7 | import '../../../get_state_manager/src/simple/list_notifier.dart'; |
| 8 | 8 | ||
| 9 | -class GetDelegate extends RouterDelegate<GetNavConfig> with ListNotifierMixin { | 9 | +class GetDelegate extends RouterDelegate<GetNavConfig> |
| 10 | + with ListNotifierSingleMixin { | ||
| 10 | final List<GetNavConfig> history = <GetNavConfig>[]; | 11 | final List<GetNavConfig> history = <GetNavConfig>[]; |
| 11 | final PopMode backButtonPopMode; | 12 | final PopMode backButtonPopMode; |
| 12 | final PreventDuplicateHandlingMode preventDuplicateHandlingMode; | 13 | final PreventDuplicateHandlingMode preventDuplicateHandlingMode; |
| @@ -106,7 +106,7 @@ class GetStream<T> { | @@ -106,7 +106,7 @@ class GetStream<T> { | ||
| 106 | late T _value; | 106 | late T _value; |
| 107 | 107 | ||
| 108 | T get value { | 108 | T get value { |
| 109 | - RxInterface.proxy?.addListener(this); | 109 | + // RxInterface.proxy?.addListener(this); |
| 110 | return _value; | 110 | return _value; |
| 111 | } | 111 | } |
| 112 | 112 |
| @@ -4,6 +4,7 @@ import 'dart:async'; | @@ -4,6 +4,7 @@ import 'dart:async'; | ||
| 4 | import 'dart:collection'; | 4 | import 'dart:collection'; |
| 5 | 5 | ||
| 6 | import 'package:flutter/foundation.dart'; | 6 | import 'package:flutter/foundation.dart'; |
| 7 | +import 'package:get/get_state_manager/src/simple/list_notifier.dart'; | ||
| 7 | 8 | ||
| 8 | import '../rx_stream/rx_stream.dart'; | 9 | import '../rx_stream/rx_stream.dart'; |
| 9 | import '../rx_typedefs/rx_typedefs.dart'; | 10 | import '../rx_typedefs/rx_typedefs.dart'; |
| @@ -5,7 +5,7 @@ import '../../../instance_manager.dart'; | @@ -5,7 +5,7 @@ import '../../../instance_manager.dart'; | ||
| 5 | import '../../get_state_manager.dart'; | 5 | import '../../get_state_manager.dart'; |
| 6 | import '../simple/list_notifier.dart'; | 6 | import '../simple/list_notifier.dart'; |
| 7 | 7 | ||
| 8 | -mixin StateMixin<T> on ListNotifierMixin { | 8 | +mixin StateMixin<T> on ListNotifier { |
| 9 | late T _value; | 9 | late T _value; |
| 10 | RxStatus? _status; | 10 | RxStatus? _status; |
| 11 | 11 | ||
| @@ -27,7 +27,7 @@ mixin StateMixin<T> on ListNotifierMixin { | @@ -27,7 +27,7 @@ mixin StateMixin<T> on ListNotifierMixin { | ||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | RxStatus get status { | 29 | RxStatus get status { |
| 30 | - notifyChildrens(); | 30 | + reportRead(); |
| 31 | return _status ??= _status = RxStatus.loading(); | 31 | return _status ??= _status = RxStatus.loading(); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| @@ -35,7 +35,7 @@ mixin StateMixin<T> on ListNotifierMixin { | @@ -35,7 +35,7 @@ mixin StateMixin<T> on ListNotifierMixin { | ||
| 35 | 35 | ||
| 36 | @protected | 36 | @protected |
| 37 | T get value { | 37 | T get value { |
| 38 | - notifyChildrens(); | 38 | + reportRead(); |
| 39 | return _value; | 39 | return _value; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| @@ -82,7 +82,7 @@ class Value<T> extends ListNotifier | @@ -82,7 +82,7 @@ class Value<T> extends ListNotifier | ||
| 82 | 82 | ||
| 83 | @override | 83 | @override |
| 84 | T get value { | 84 | T get value { |
| 85 | - notifyChildrens(); | 85 | + reportRead(); |
| 86 | return _value; | 86 | return _value; |
| 87 | } | 87 | } |
| 88 | 88 |
| @@ -6,8 +6,7 @@ import '../rx_flutter/rx_notifier.dart'; | @@ -6,8 +6,7 @@ import '../rx_flutter/rx_notifier.dart'; | ||
| 6 | import 'list_notifier.dart'; | 6 | import 'list_notifier.dart'; |
| 7 | 7 | ||
| 8 | // ignore: prefer_mixin | 8 | // ignore: prefer_mixin |
| 9 | -abstract class GetxController extends Listenable | ||
| 10 | - with GetLifeCycleMixin, ListNotifierMixin { | 9 | +abstract class GetxController extends ListNotifier with GetLifeCycleMixin { |
| 11 | /// Rebuilds `GetBuilder` each time you call `update()`; | 10 | /// Rebuilds `GetBuilder` each time you call `update()`; |
| 12 | /// Can take a List of [ids], that will only update the matching | 11 | /// Can take a List of [ids], that will only update the matching |
| 13 | /// `GetBuilder( id: )`, | 12 | /// `GetBuilder( id: )`, |
| 1 | import 'dart:collection'; | 1 | import 'dart:collection'; |
| 2 | 2 | ||
| 3 | -import 'package:flutter/widgets.dart'; | 3 | +import 'package:flutter/foundation.dart'; |
| 4 | 4 | ||
| 5 | // This callback remove the listener on addListener function | 5 | // This callback remove the listener on addListener function |
| 6 | typedef Disposer = void Function(); | 6 | typedef Disposer = void Function(); |
| @@ -9,42 +9,50 @@ typedef Disposer = void Function(); | @@ -9,42 +9,50 @@ typedef Disposer = void Function(); | ||
| 9 | // if it brings overhead the extra call, | 9 | // if it brings overhead the extra call, |
| 10 | typedef GetStateUpdate = void Function(); | 10 | typedef GetStateUpdate = void Function(); |
| 11 | 11 | ||
| 12 | -class ListNotifier extends Listenable with ListNotifierMixin {} | 12 | +class ListNotifier extends Listenable |
| 13 | + with ListNotifierSingleMixin, ListNotifierGroupMixin {} | ||
| 13 | 14 | ||
| 14 | -mixin ListNotifierMixin on Listenable { | 15 | +class ListNotifierSingle = ListNotifier with ListNotifierSingleMixin; |
| 16 | + | ||
| 17 | +class ListNotifierGroup = ListNotifier with ListNotifierGroupMixin; | ||
| 18 | + | ||
| 19 | +mixin ListNotifierSingleMixin on Listenable { | ||
| 15 | List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[]; | 20 | List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[]; |
| 16 | 21 | ||
| 17 | - HashMap<Object?, List<GetStateUpdate>>? _updatersGroupIds = | ||
| 18 | - HashMap<Object?, List<GetStateUpdate>>(); | 22 | + @override |
| 23 | + Disposer addListener(GetStateUpdate listener) { | ||
| 24 | + assert(_debugAssertNotDisposed()); | ||
| 25 | + _updaters!.add(listener); | ||
| 26 | + return () => _updaters!.remove(listener); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + bool containsListener(GetStateUpdate listener) { | ||
| 30 | + return _updaters?.contains(listener) ?? false; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + @override | ||
| 34 | + void removeListener(VoidCallback listener) { | ||
| 35 | + assert(_debugAssertNotDisposed()); | ||
| 36 | + _updaters!.remove(listener); | ||
| 37 | + } | ||
| 19 | 38 | ||
| 20 | @protected | 39 | @protected |
| 21 | void refresh() { | 40 | void refresh() { |
| 22 | assert(_debugAssertNotDisposed()); | 41 | assert(_debugAssertNotDisposed()); |
| 23 | - | ||
| 24 | _notifyUpdate(); | 42 | _notifyUpdate(); |
| 25 | } | 43 | } |
| 26 | 44 | ||
| 45 | + @protected | ||
| 46 | + void reportRead() { | ||
| 47 | + TaskManager.instance.notify(this); | ||
| 48 | + } | ||
| 49 | + | ||
| 27 | void _notifyUpdate() { | 50 | void _notifyUpdate() { |
| 28 | for (var element in _updaters!) { | 51 | for (var element in _updaters!) { |
| 29 | element!(); | 52 | element!(); |
| 30 | } | 53 | } |
| 31 | } | 54 | } |
| 32 | 55 | ||
| 33 | - void _notifyIdUpdate(Object id) { | ||
| 34 | - if (_updatersGroupIds!.containsKey(id)) { | ||
| 35 | - final listGroup = _updatersGroupIds![id]!; | ||
| 36 | - for (var item in listGroup) { | ||
| 37 | - item(); | ||
| 38 | - } | ||
| 39 | - } | ||
| 40 | - } | ||
| 41 | - | ||
| 42 | - @protected | ||
| 43 | - void refreshGroup(Object id) { | ||
| 44 | - assert(_debugAssertNotDisposed()); | ||
| 45 | - _notifyIdUpdate(id); | ||
| 46 | - } | ||
| 47 | - | ||
| 48 | bool _debugAssertNotDisposed() { | 56 | bool _debugAssertNotDisposed() { |
| 49 | assert(() { | 57 | assert(() { |
| 50 | if (_updaters == null) { | 58 | if (_updaters == null) { |
| @@ -56,59 +64,79 @@ mixin ListNotifierMixin on Listenable { | @@ -56,59 +64,79 @@ mixin ListNotifierMixin on Listenable { | ||
| 56 | return true; | 64 | return true; |
| 57 | } | 65 | } |
| 58 | 66 | ||
| 59 | - @protected | ||
| 60 | - void notifyChildrens() { | ||
| 61 | - TaskManager.instance.notify(_updaters); | 67 | + int get listenersLength { |
| 68 | + assert(_debugAssertNotDisposed()); | ||
| 69 | + return _updaters!.length; | ||
| 62 | } | 70 | } |
| 63 | 71 | ||
| 64 | - bool get hasListeners { | 72 | + @mustCallSuper |
| 73 | + void dispose() { | ||
| 65 | assert(_debugAssertNotDisposed()); | 74 | assert(_debugAssertNotDisposed()); |
| 66 | - return _updaters!.isNotEmpty; | 75 | + _updaters = null; |
| 67 | } | 76 | } |
| 77 | +} | ||
| 78 | + | ||
| 79 | +mixin ListNotifierGroupMixin on Listenable { | ||
| 80 | + HashMap<Object?, ListNotifierSingleMixin>? _updatersGroupIds = | ||
| 81 | + HashMap<Object?, ListNotifierSingleMixin>(); | ||
| 68 | 82 | ||
| 69 | - int get listeners { | 83 | + void _notifyGroupUpdate(Object id) { |
| 84 | + if (_updatersGroupIds!.containsKey(id)) { | ||
| 85 | + _updatersGroupIds![id]!._notifyUpdate(); | ||
| 86 | + } | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + @protected | ||
| 90 | + void notifyGroupChildrens(Object id) { | ||
| 70 | assert(_debugAssertNotDisposed()); | 91 | assert(_debugAssertNotDisposed()); |
| 71 | - return _updaters!.length; | 92 | + TaskManager.instance.notify(_updatersGroupIds![id]!); |
| 72 | } | 93 | } |
| 73 | 94 | ||
| 74 | - @override | ||
| 75 | - void removeListener(VoidCallback listener) { | 95 | + bool containsId(Object id) { |
| 96 | + return _updatersGroupIds?.containsKey(id) ?? false; | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + @protected | ||
| 100 | + void refreshGroup(Object id) { | ||
| 76 | assert(_debugAssertNotDisposed()); | 101 | assert(_debugAssertNotDisposed()); |
| 77 | - _updaters!.remove(listener); | 102 | + _notifyGroupUpdate(id); |
| 103 | + } | ||
| 104 | + | ||
| 105 | + bool _debugAssertNotDisposed() { | ||
| 106 | + assert(() { | ||
| 107 | + if (_updatersGroupIds == null) { | ||
| 108 | + throw FlutterError('''A $runtimeType was used after being disposed.\n | ||
| 109 | +'Once you have called dispose() on a $runtimeType, it can no longer be used.'''); | ||
| 110 | + } | ||
| 111 | + return true; | ||
| 112 | + }()); | ||
| 113 | + return true; | ||
| 78 | } | 114 | } |
| 79 | 115 | ||
| 80 | void removeListenerId(Object id, VoidCallback listener) { | 116 | void removeListenerId(Object id, VoidCallback listener) { |
| 81 | assert(_debugAssertNotDisposed()); | 117 | assert(_debugAssertNotDisposed()); |
| 82 | if (_updatersGroupIds!.containsKey(id)) { | 118 | if (_updatersGroupIds!.containsKey(id)) { |
| 83 | - _updatersGroupIds![id]!.remove(listener); | 119 | + _updatersGroupIds![id]!.removeListener(listener); |
| 84 | } | 120 | } |
| 85 | - _updaters!.remove(listener); | ||
| 86 | } | 121 | } |
| 87 | 122 | ||
| 88 | @mustCallSuper | 123 | @mustCallSuper |
| 89 | void dispose() { | 124 | void dispose() { |
| 90 | assert(_debugAssertNotDisposed()); | 125 | assert(_debugAssertNotDisposed()); |
| 91 | - _updaters = null; | 126 | + _updatersGroupIds?.forEach((key, value) => value.dispose()); |
| 92 | _updatersGroupIds = null; | 127 | _updatersGroupIds = null; |
| 93 | } | 128 | } |
| 94 | 129 | ||
| 95 | - @override | ||
| 96 | - Disposer addListener(GetStateUpdate listener) { | ||
| 97 | - assert(_debugAssertNotDisposed()); | ||
| 98 | - _updaters!.add(listener); | ||
| 99 | - return () => _updaters!.remove(listener); | ||
| 100 | - } | ||
| 101 | - | ||
| 102 | Disposer addListenerId(Object? key, GetStateUpdate listener) { | 130 | Disposer addListenerId(Object? key, GetStateUpdate listener) { |
| 103 | - _updatersGroupIds![key] ??= <GetStateUpdate>[]; | ||
| 104 | - _updatersGroupIds![key]!.add(listener); | ||
| 105 | - return () => _updatersGroupIds![key]!.remove(listener); | 131 | + _updatersGroupIds![key] ??= ListNotifierSingle(); |
| 132 | + return _updatersGroupIds![key]!.addListener(listener); | ||
| 106 | } | 133 | } |
| 107 | 134 | ||
| 108 | /// To dispose an [id] from future updates(), this ids are registered | 135 | /// To dispose an [id] from future updates(), this ids are registered |
| 109 | /// by `GetBuilder()` or similar, so is a way to unlink the state change with | 136 | /// by `GetBuilder()` or similar, so is a way to unlink the state change with |
| 110 | /// the Widget from the Controller. | 137 | /// the Widget from the Controller. |
| 111 | void disposeId(Object id) { | 138 | void disposeId(Object id) { |
| 139 | + _updatersGroupIds?[id]?.dispose(); | ||
| 112 | _updatersGroupIds!.remove(id); | 140 | _updatersGroupIds!.remove(id); |
| 113 | } | 141 | } |
| 114 | } | 142 | } |
| @@ -123,11 +151,18 @@ class TaskManager { | @@ -123,11 +151,18 @@ class TaskManager { | ||
| 123 | GetStateUpdate? _setter; | 151 | GetStateUpdate? _setter; |
| 124 | List<VoidCallback>? _remove; | 152 | List<VoidCallback>? _remove; |
| 125 | 153 | ||
| 126 | - void notify(List<GetStateUpdate?>? _updaters) { | ||
| 127 | - if (_setter != null) { | ||
| 128 | - if (!_updaters!.contains(_setter)) { | ||
| 129 | - _updaters.add(_setter); | ||
| 130 | - _remove!.add(() => _updaters.remove(_setter)); | 154 | + final listNotifier = ListNotifierGroup(); |
| 155 | + | ||
| 156 | + // void addElement(Object id, GetStateUpdate listener) { | ||
| 157 | + // _remove?.add(listNotifier.addListenerId(id, listener)); | ||
| 158 | + // } | ||
| 159 | + | ||
| 160 | + void notify(ListNotifierSingleMixin _updaters) { | ||
| 161 | + final listener = _setter; | ||
| 162 | + if (listener != null) { | ||
| 163 | + if (!_updaters.containsListener(listener)) { | ||
| 164 | + _updaters.addListener(listener); | ||
| 165 | + _remove?.add(() => _updaters.removeListener(listener)); | ||
| 131 | } | 166 | } |
| 132 | } | 167 | } |
| 133 | } | 168 | } |
-
Please register or login to post a comment