Jonny Borges
Committed by GitHub

Merge pull request #2033 from NatsuOnFire/feature/add_ticker_provider_mixin

Add GetTickerProviderStateMixin when multiple AnimationController objects are used
... ... @@ -36,13 +36,13 @@ mixin GetSingleTickerProviderStateMixin on GetxController
if (_ticker == null) return true;
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary(
'$runtimeType is a SingleTickerProviderStateMixin but multiple tickers were created.'),
'$runtimeType is a GetSingleTickerProviderStateMixin but multiple tickers were created.'),
ErrorDescription(
'A SingleTickerProviderStateMixin can only be used as a TickerProvider once.'),
'A GetSingleTickerProviderStateMixin can only be used as a TickerProvider once.'),
ErrorHint(
'If a State is used for multiple AnimationController objects, or if it is passed to other '
'objects and those objects might use it more than one time in total, then instead of '
'mixing in a SingleTickerProviderStateMixin, use a regular TickerProviderStateMixin.',
'mixing in a GetSingleTickerProviderStateMixin, use a regular GetTickerProviderStateMixin.',
),
]);
}());
... ... @@ -66,7 +66,7 @@ mixin GetSingleTickerProviderStateMixin on GetxController
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('$this was disposed with an active Ticker.'),
ErrorDescription(
'$runtimeType created a Ticker via its SingleTickerProviderStateMixin, but at the time '
'$runtimeType created a Ticker via its GetSingleTickerProviderStateMixin, but at the time '
'dispose() was called on the mixin, that Ticker was still active. The Ticker must '
'be disposed before calling super.dispose().',
),
... ... @@ -82,6 +82,99 @@ mixin GetSingleTickerProviderStateMixin on GetxController
}
}
/// Used like `TickerProviderMixin` but only with Get Controllers.
/// Simplifies multiple AnimationController creation inside GetxController.
///
/// Example:
///```
///class SplashController extends GetxController with
/// GetTickerProviderStateMixin {
/// AnimationController first_controller;
/// AnimationController second_controller;
///
/// @override
/// void onInit() {
/// final duration = const Duration(seconds: 2);
/// first_controller =
/// AnimationController.unbounded(duration: duration, vsync: this);
/// second_controller =
/// AnimationController.unbounded(duration: duration, vsync: this);
/// first_controller.repeat();
/// first_controller.addListener(() =>
/// print("Animation Controller value: ${first_controller.value}"));
/// second_controller.addListener(() =>
/// print("Animation Controller value: ${second_controller.value}"));
/// }
/// ...
/// ```
mixin GetTickerProviderStateMixin on GetxController implements TickerProvider {
Set<Ticker>? _tickers;
@override
Ticker createTicker(TickerCallback onTick) {
_tickers ??= <_WidgetTicker>{};
final result = _WidgetTicker(onTick, this, debugLabel: kDebugMode ? 'created by ${describeIdentity(this)}' : null);
_tickers!.add(result);
return result;
}
void _removeTicker(_WidgetTicker ticker) {
assert(_tickers != null);
assert(_tickers!.contains(ticker));
_tickers!.remove(ticker);
}
void didChangeDependencies(BuildContext context) {
final muted = !TickerMode.of(context);
if (_tickers != null) {
for (final ticker in _tickers!) {
ticker.muted = muted;
}
}
}
@override
void onClose() {
assert(() {
if (_tickers != null) {
for (final ticker in _tickers!) {
if (ticker.isActive) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('$this was disposed with an active Ticker.'),
ErrorDescription(
'$runtimeType created a Ticker via its GetTickerProviderStateMixin, but at the time '
'dispose() was called on the mixin, that Ticker was still active. All Tickers must '
'be disposed before calling super.dispose().',
),
ErrorHint(
'Tickers used by AnimationControllers '
'should be disposed by calling dispose() on the AnimationController itself. '
'Otherwise, the ticker will leak.',
),
ticker.describeForError('The offending ticker was'),
]);
}
}
}
return true;
}());
super.onClose();
}
}
class _WidgetTicker extends Ticker {
_WidgetTicker(TickerCallback onTick, this._creator, { String? debugLabel }) : super(onTick, debugLabel: debugLabel);
final GetTickerProviderStateMixin _creator;
@override
void dispose() {
_creator._removeTicker(this);
super.dispose();
}
}
@Deprecated('use GetSingleTickerProviderStateMixin')
/// Used like `SingleTickerProviderMixin` but only with Get Controllers.
... ...