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: ${first_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