Committed by
GitHub
Merge pull request #2033 from NatsuOnFire/feature/add_ticker_provider_mixin
Add GetTickerProviderStateMixin when multiple AnimationController objects are used
Showing
1 changed file
with
97 additions
and
4 deletions
| @@ -36,13 +36,13 @@ mixin GetSingleTickerProviderStateMixin on GetxController | @@ -36,13 +36,13 @@ mixin GetSingleTickerProviderStateMixin on GetxController | ||
| 36 | if (_ticker == null) return true; | 36 | if (_ticker == null) return true; |
| 37 | throw FlutterError.fromParts(<DiagnosticsNode>[ | 37 | throw FlutterError.fromParts(<DiagnosticsNode>[ |
| 38 | ErrorSummary( | 38 | ErrorSummary( |
| 39 | - '$runtimeType is a SingleTickerProviderStateMixin but multiple tickers were created.'), | 39 | + '$runtimeType is a GetSingleTickerProviderStateMixin but multiple tickers were created.'), |
| 40 | ErrorDescription( | 40 | ErrorDescription( |
| 41 | - 'A SingleTickerProviderStateMixin can only be used as a TickerProvider once.'), | 41 | + 'A GetSingleTickerProviderStateMixin can only be used as a TickerProvider once.'), |
| 42 | ErrorHint( | 42 | ErrorHint( |
| 43 | 'If a State is used for multiple AnimationController objects, or if it is passed to other ' | 43 | 'If a State is used for multiple AnimationController objects, or if it is passed to other ' |
| 44 | 'objects and those objects might use it more than one time in total, then instead of ' | 44 | 'objects and those objects might use it more than one time in total, then instead of ' |
| 45 | - 'mixing in a SingleTickerProviderStateMixin, use a regular TickerProviderStateMixin.', | 45 | + 'mixing in a GetSingleTickerProviderStateMixin, use a regular GetTickerProviderStateMixin.', |
| 46 | ), | 46 | ), |
| 47 | ]); | 47 | ]); |
| 48 | }()); | 48 | }()); |
| @@ -66,7 +66,7 @@ mixin GetSingleTickerProviderStateMixin on GetxController | @@ -66,7 +66,7 @@ mixin GetSingleTickerProviderStateMixin on GetxController | ||
| 66 | throw FlutterError.fromParts(<DiagnosticsNode>[ | 66 | throw FlutterError.fromParts(<DiagnosticsNode>[ |
| 67 | ErrorSummary('$this was disposed with an active Ticker.'), | 67 | ErrorSummary('$this was disposed with an active Ticker.'), |
| 68 | ErrorDescription( | 68 | ErrorDescription( |
| 69 | - '$runtimeType created a Ticker via its SingleTickerProviderStateMixin, but at the time ' | 69 | + '$runtimeType created a Ticker via its GetSingleTickerProviderStateMixin, but at the time ' |
| 70 | 'dispose() was called on the mixin, that Ticker was still active. The Ticker must ' | 70 | 'dispose() was called on the mixin, that Ticker was still active. The Ticker must ' |
| 71 | 'be disposed before calling super.dispose().', | 71 | 'be disposed before calling super.dispose().', |
| 72 | ), | 72 | ), |
| @@ -82,6 +82,99 @@ mixin GetSingleTickerProviderStateMixin on GetxController | @@ -82,6 +82,99 @@ mixin GetSingleTickerProviderStateMixin on GetxController | ||
| 82 | } | 82 | } |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | +/// Used like `TickerProviderMixin` but only with Get Controllers. | ||
| 86 | +/// Simplifies multiple AnimationController creation inside GetxController. | ||
| 87 | +/// | ||
| 88 | +/// Example: | ||
| 89 | +///``` | ||
| 90 | +///class SplashController extends GetxController with | ||
| 91 | +/// GetTickerProviderStateMixin { | ||
| 92 | +/// AnimationController first_controller; | ||
| 93 | +/// AnimationController second_controller; | ||
| 94 | +/// | ||
| 95 | +/// @override | ||
| 96 | +/// void onInit() { | ||
| 97 | +/// final duration = const Duration(seconds: 2); | ||
| 98 | +/// first_controller = | ||
| 99 | +/// AnimationController.unbounded(duration: duration, vsync: this); | ||
| 100 | +/// second_controller = | ||
| 101 | +/// AnimationController.unbounded(duration: duration, vsync: this); | ||
| 102 | +/// first_controller.repeat(); | ||
| 103 | +/// first_controller.addListener(() => | ||
| 104 | +/// print("Animation Controller value: ${first_controller.value}")); | ||
| 105 | +/// second_controller.addListener(() => | ||
| 106 | +/// print("Animation Controller value: ${second_controller.value}")); | ||
| 107 | +/// } | ||
| 108 | +/// ... | ||
| 109 | +/// ``` | ||
| 110 | +mixin GetTickerProviderStateMixin on GetxController implements TickerProvider { | ||
| 111 | + Set<Ticker>? _tickers; | ||
| 112 | + | ||
| 113 | + @override | ||
| 114 | + Ticker createTicker(TickerCallback onTick) { | ||
| 115 | + _tickers ??= <_WidgetTicker>{}; | ||
| 116 | + final result = _WidgetTicker(onTick, this, debugLabel: kDebugMode ? 'created by ${describeIdentity(this)}' : null); | ||
| 117 | + _tickers!.add(result); | ||
| 118 | + return result; | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + void _removeTicker(_WidgetTicker ticker) { | ||
| 122 | + assert(_tickers != null); | ||
| 123 | + assert(_tickers!.contains(ticker)); | ||
| 124 | + _tickers!.remove(ticker); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + void didChangeDependencies(BuildContext context) { | ||
| 128 | + final muted = !TickerMode.of(context); | ||
| 129 | + if (_tickers != null) { | ||
| 130 | + for (final ticker in _tickers!) { | ||
| 131 | + ticker.muted = muted; | ||
| 132 | + } | ||
| 133 | + } | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + @override | ||
| 137 | + void onClose() { | ||
| 138 | + assert(() { | ||
| 139 | + if (_tickers != null) { | ||
| 140 | + for (final ticker in _tickers!) { | ||
| 141 | + if (ticker.isActive) { | ||
| 142 | + throw FlutterError.fromParts(<DiagnosticsNode>[ | ||
| 143 | + ErrorSummary('$this was disposed with an active Ticker.'), | ||
| 144 | + ErrorDescription( | ||
| 145 | + '$runtimeType created a Ticker via its GetTickerProviderStateMixin, but at the time ' | ||
| 146 | + 'dispose() was called on the mixin, that Ticker was still active. All Tickers must ' | ||
| 147 | + 'be disposed before calling super.dispose().', | ||
| 148 | + ), | ||
| 149 | + ErrorHint( | ||
| 150 | + 'Tickers used by AnimationControllers ' | ||
| 151 | + 'should be disposed by calling dispose() on the AnimationController itself. ' | ||
| 152 | + 'Otherwise, the ticker will leak.', | ||
| 153 | + ), | ||
| 154 | + ticker.describeForError('The offending ticker was'), | ||
| 155 | + ]); | ||
| 156 | + } | ||
| 157 | + } | ||
| 158 | + } | ||
| 159 | + return true; | ||
| 160 | + }()); | ||
| 161 | + super.onClose(); | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | +} | ||
| 165 | + | ||
| 166 | +class _WidgetTicker extends Ticker { | ||
| 167 | + _WidgetTicker(TickerCallback onTick, this._creator, { String? debugLabel }) : super(onTick, debugLabel: debugLabel); | ||
| 168 | + | ||
| 169 | + final GetTickerProviderStateMixin _creator; | ||
| 170 | + | ||
| 171 | + @override | ||
| 172 | + void dispose() { | ||
| 173 | + _creator._removeTicker(this); | ||
| 174 | + super.dispose(); | ||
| 175 | + } | ||
| 176 | +} | ||
| 177 | + | ||
| 85 | @Deprecated('use GetSingleTickerProviderStateMixin') | 178 | @Deprecated('use GetSingleTickerProviderStateMixin') |
| 86 | 179 | ||
| 87 | /// Used like `SingleTickerProviderMixin` but only with Get Controllers. | 180 | /// Used like `SingleTickerProviderMixin` but only with Get Controllers. |
-
Please register or login to post a comment