optimize GetBuilder "group id" using `HashSet`
- `Changed HashMap<int,GetStateUpdate>` to `HashSet<GetStateUpdate>`. Reference https://github.com/jonataslaw/getx/pull/565#discussion_r484088390 - Added a internal VoidCallback in `GetStateUpdaterMixin::getUpdate`, to see if it reduces overhead of anonym function in `setState()` (considering GC).
Showing
1 changed file
with
28 additions
and
27 deletions
| @@ -12,7 +12,9 @@ import 'simple_builder.dart'; | @@ -12,7 +12,9 @@ import 'simple_builder.dart'; | ||
| 12 | //typedef Disposer = void Function(); | 12 | //typedef Disposer = void Function(); |
| 13 | 13 | ||
| 14 | // replacing StateSetter, return if the Widget is mounted for extra validation. | 14 | // replacing StateSetter, return if the Widget is mounted for extra validation. |
| 15 | +// if it brings overhead the extra call, | ||
| 15 | typedef GetStateUpdate = bool Function(); | 16 | typedef GetStateUpdate = bool Function(); |
| 17 | +//typedef GetStateUpdate = void Function(VoidCallback fn); | ||
| 16 | 18 | ||
| 17 | /// Complies with [GetStateUpdater] | 19 | /// Complies with [GetStateUpdater] |
| 18 | /// | 20 | /// |
| @@ -24,9 +26,14 @@ typedef GetStateUpdate = bool Function(); | @@ -24,9 +26,14 @@ typedef GetStateUpdate = bool Function(); | ||
| 24 | /// TODO: check performance HIT for the extra method call. | 26 | /// TODO: check performance HIT for the extra method call. |
| 25 | /// | 27 | /// |
| 26 | mixin GetStateUpdaterMixin<T extends StatefulWidget> on State<T> { | 28 | mixin GetStateUpdaterMixin<T extends StatefulWidget> on State<T> { |
| 29 | + // To avoid the creation of an anonym function to be GC later. | ||
| 30 | + static VoidCallback _stateCallback = () {}; | ||
| 31 | + | ||
| 32 | + /// Experimental method to replace setState((){}); | ||
| 33 | + /// Used with GetStateUpdate. | ||
| 27 | bool getUpdate() { | 34 | bool getUpdate() { |
| 28 | final _mounted = mounted; | 35 | final _mounted = mounted; |
| 29 | - if (_mounted) setState(() {}); | 36 | + if (_mounted) setState(_stateCallback); |
| 30 | return _mounted; | 37 | return _mounted; |
| 31 | } | 38 | } |
| 32 | } | 39 | } |
| @@ -37,10 +44,7 @@ class GetxController extends DisposableInterface { | @@ -37,10 +44,7 @@ class GetxController extends DisposableInterface { | ||
| 37 | // final _updatersIds = HashMap<String, StateSetter>(); //<old> | 44 | // final _updatersIds = HashMap<String, StateSetter>(); //<old> |
| 38 | final _updatersIds = HashMap<String, GetStateUpdate>(); | 45 | final _updatersIds = HashMap<String, GetStateUpdate>(); |
| 39 | 46 | ||
| 40 | -// final _updatersGroupIds = HashMap<String, List>(); //<old> | ||
| 41 | - final _updatersGroupIds = HashMap<String, HashMap<int, GetStateUpdate>>(); | ||
| 42 | - | ||
| 43 | - static int _groupIdCount = 0; | 47 | + final _updatersGroupIds = HashMap<String, HashSet<GetStateUpdate>>(); |
| 44 | 48 | ||
| 45 | /// Rebuilds [GetBuilder] each time you call [update()]; | 49 | /// Rebuilds [GetBuilder] each time you call [update()]; |
| 46 | /// Can take a List of [ids], that will only update the matching | 50 | /// Can take a List of [ids], that will only update the matching |
| @@ -50,14 +54,21 @@ class GetxController extends DisposableInterface { | @@ -50,14 +54,21 @@ class GetxController extends DisposableInterface { | ||
| 50 | void update([List<String> ids, bool condition = true]) { | 54 | void update([List<String> ids, bool condition = true]) { |
| 51 | if (!condition) return; | 55 | if (!condition) return; |
| 52 | if (ids == null) { | 56 | if (ids == null) { |
| 53 | -// _updaters.forEach((rs) => rs(() {}));//<old> | 57 | +// _updaters?.forEach((rs) => rs(() {})); //<old> |
| 54 | _updaters.forEach((rs) => rs()); | 58 | _updaters.forEach((rs) => rs()); |
| 55 | } else { | 59 | } else { |
| 56 | - ids.forEach((element) { | ||
| 57 | -// _updatersGroupIds[element]?.forEach((k, rs) => rs(() {}));//<old> | ||
| 58 | -// _updatersIds[element]?.call(() {});//<old> | ||
| 59 | - _updatersIds[element]?.call(); | ||
| 60 | - _updatersGroupIds[element]?.forEach((k, rs) => rs()); | 60 | + // @jonny, remove this commented code if it's not more optimized. |
| 61 | +// for (final id in ids) { | ||
| 62 | +// if (_updatersIds[id] != null) _updatersIds[id](); | ||
| 63 | +// if (_updatersGroupIds[id] != null) | ||
| 64 | +// for (final rs in _updatersGroupIds[id]) rs(); | ||
| 65 | +// } | ||
| 66 | + | ||
| 67 | + ids.forEach((id) { | ||
| 68 | +// _updatersIds[id]?.call(() {}); //<old> | ||
| 69 | +// _updatersGroupIds[id]?.forEach((rs) => rs(() {})); //<old> | ||
| 70 | + _updatersIds[id]?.call(); | ||
| 71 | + _updatersGroupIds[id]?.forEach((rs) => rs()); | ||
| 61 | }); | 72 | }); |
| 62 | } | 73 | } |
| 63 | } | 74 | } |
| @@ -72,13 +83,10 @@ class GetxController extends DisposableInterface { | @@ -72,13 +83,10 @@ class GetxController extends DisposableInterface { | ||
| 72 | VoidCallback addListenerId(String key, GetStateUpdate listener) { | 83 | VoidCallback addListenerId(String key, GetStateUpdate listener) { |
| 73 | // _printCurrentIds(); | 84 | // _printCurrentIds(); |
| 74 | if (_updatersIds.containsKey(key)) { | 85 | if (_updatersIds.containsKey(key)) { |
| 75 | - final _innerKey = _groupIdCount++; | ||
| 76 | -// final _ref = _updatersGroupIds[key] ??= HashMap<int, StateSetter>();//<old> | ||
| 77 | - final _ref = _updatersGroupIds[key] ??= HashMap<int, GetStateUpdate>(); | ||
| 78 | - _ref[_innerKey] = listener; | 86 | + _updatersGroupIds[key] ??= HashSet<GetStateUpdate>.identity(); |
| 87 | + _updatersGroupIds[key].add(listener); | ||
| 79 | return () { | 88 | return () { |
| 80 | - _ref?.remove(_innerKey); | ||
| 81 | -// _printCurrentIds(); | 89 | + _updatersGroupIds[key].remove(listener); |
| 82 | }; | 90 | }; |
| 83 | } else { | 91 | } else { |
| 84 | _updatersIds[key] = listener; | 92 | _updatersIds[key] = listener; |
| @@ -148,10 +156,6 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | @@ -148,10 +156,6 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | ||
| 148 | with GetStateUpdaterMixin { | 156 | with GetStateUpdaterMixin { |
| 149 | GetxController controller; | 157 | GetxController controller; |
| 150 | bool isCreator = false; | 158 | bool isCreator = false; |
| 151 | - | ||
| 152 | - /// TODO: @jonny, you intend to use disposers? | ||
| 153 | -// final HashSet<Disposer> disposers = HashSet<Disposer>(); | ||
| 154 | - | ||
| 155 | VoidCallback remove; | 159 | VoidCallback remove; |
| 156 | 160 | ||
| 157 | @override | 161 | @override |
| @@ -195,8 +199,8 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | @@ -195,8 +199,8 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | ||
| 195 | void _subscribeToController() { | 199 | void _subscribeToController() { |
| 196 | remove?.call(); | 200 | remove?.call(); |
| 197 | remove = (widget.id == null) | 201 | remove = (widget.id == null) |
| 198 | -// ? controller?.addListener(setState)//<old> | ||
| 199 | -// : controller?.addListenerId(widget.id, setState);//<old> | 202 | +// ? controller?.addListener(setState) //<old> |
| 203 | +// : controller?.addListenerId(widget.id, setState); //<old> | ||
| 200 | ? controller?.addListener(getUpdate) | 204 | ? controller?.addListener(getUpdate) |
| 201 | : controller?.addListenerId(widget.id, getUpdate); | 205 | : controller?.addListenerId(widget.id, getUpdate); |
| 202 | } | 206 | } |
| @@ -218,10 +222,6 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | @@ -218,10 +222,6 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | ||
| 218 | } | 222 | } |
| 219 | } | 223 | } |
| 220 | remove?.call(); | 224 | remove?.call(); |
| 221 | - | ||
| 222 | -// disposers.forEach((element) { | ||
| 223 | -// element(); | ||
| 224 | -// }); | ||
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | @override | 227 | @override |
| @@ -251,6 +251,7 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | @@ -251,6 +251,7 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | ||
| 251 | /// like Rx() does with Obx(). | 251 | /// like Rx() does with Obx(). |
| 252 | class Value<T> extends GetxController { | 252 | class Value<T> extends GetxController { |
| 253 | Value([this._value]); | 253 | Value([this._value]); |
| 254 | + | ||
| 254 | T _value; | 255 | T _value; |
| 255 | 256 | ||
| 256 | T get value { | 257 | T get value { |
-
Please register or login to post a comment