Unverified Commit ded49cda authored by Dan Field's avatar Dan Field Committed by GitHub

Assert when calling a method that tries to use the ticker unsafely after dispose (#26991)

parent 19b8d2e0
...@@ -436,6 +436,11 @@ class AnimationController extends Animation<double> ...@@ -436,6 +436,11 @@ class AnimationController extends Animation<double>
} }
return true; return true;
}()); }());
assert(
_ticker != null,
'AnimationController.forward() called after AnimationController.dispose()\n'
'AnimationController methods should not be used after calling dispose.'
);
_direction = _AnimationDirection.forward; _direction = _AnimationDirection.forward;
if (from != null) if (from != null)
value = from; value = from;
...@@ -464,6 +469,11 @@ class AnimationController extends Animation<double> ...@@ -464,6 +469,11 @@ class AnimationController extends Animation<double>
} }
return true; return true;
}()); }());
assert(
_ticker != null,
'AnimationController.reverse() called after AnimationController.dispose()\n'
'AnimationController methods should not be used after calling dispose.'
);
_direction = _AnimationDirection.reverse; _direction = _AnimationDirection.reverse;
if (from != null) if (from != null)
value = from; value = from;
...@@ -483,6 +493,11 @@ class AnimationController extends Animation<double> ...@@ -483,6 +493,11 @@ class AnimationController extends Animation<double>
/// animation, when `target` is reached, [status] is reported as /// animation, when `target` is reached, [status] is reported as
/// [AnimationStatus.completed]. /// [AnimationStatus.completed].
TickerFuture animateTo(double target, { Duration duration, Curve curve = Curves.linear }) { TickerFuture animateTo(double target, { Duration duration, Curve curve = Curves.linear }) {
assert(
_ticker != null,
'AnimationController.animateTo() called after AnimationController.dispose()\n'
'AnimationController methods should not be used after calling dispose.'
);
_direction = _AnimationDirection.forward; _direction = _AnimationDirection.forward;
return _animateToInternal(target, duration: duration, curve: curve); return _animateToInternal(target, duration: duration, curve: curve);
} }
...@@ -500,6 +515,11 @@ class AnimationController extends Animation<double> ...@@ -500,6 +515,11 @@ class AnimationController extends Animation<double>
/// animation, when `target` is reached, [status] is reported as /// animation, when `target` is reached, [status] is reported as
/// [AnimationStatus.dismissed]. /// [AnimationStatus.dismissed].
TickerFuture animateBack(double target, { Duration duration, Curve curve = Curves.linear }) { TickerFuture animateBack(double target, { Duration duration, Curve curve = Curves.linear }) {
assert(
_ticker != null,
'AnimationController.animateBack() called after AnimationController.dispose()\n'
'AnimationController methods should not be used after calling dispose.'
);
_direction = _AnimationDirection.reverse; _direction = _AnimationDirection.reverse;
return _animateToInternal(target, duration: duration, curve: curve); return _animateToInternal(target, duration: duration, curve: curve);
} }
...@@ -626,6 +646,11 @@ class AnimationController extends Animation<double> ...@@ -626,6 +646,11 @@ class AnimationController extends Animation<double>
/// canceled, meaning the future never completes and its [TickerFuture.orCancel] /// canceled, meaning the future never completes and its [TickerFuture.orCancel]
/// derivative future completes with a [TickerCanceled] error. /// derivative future completes with a [TickerCanceled] error.
TickerFuture animateWith(Simulation simulation) { TickerFuture animateWith(Simulation simulation) {
assert(
_ticker != null,
'AnimationController.animateWith() called after AnimationController.dispose()\n'
'AnimationController methods should not be used after calling dispose.'
);
stop(); stop();
return _startSimulation(simulation); return _startSimulation(simulation);
} }
...@@ -662,6 +687,11 @@ class AnimationController extends Animation<double> ...@@ -662,6 +687,11 @@ class AnimationController extends Animation<double>
/// * [forward], [reverse], [animateTo], [animateWith], [fling], and [repeat], /// * [forward], [reverse], [animateTo], [animateWith], [fling], and [repeat],
/// which restart the animation controller. /// which restart the animation controller.
void stop({ bool canceled = true }) { void stop({ bool canceled = true }) {
assert(
_ticker != null,
'AnimationController.stop() called after AnimationController.dispose()\n'
'AnimationController methods should not be used after calling dispose.'
);
_simulation = null; _simulation = null;
_lastElapsedDuration = null; _lastElapsedDuration = null;
_ticker.stop(canceled: canceled); _ticker.stop(canceled: canceled);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:flutter/physics.dart';
import 'package:flutter/semantics.dart'; import 'package:flutter/semantics.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/animation.dart'; import 'package:flutter/animation.dart';
...@@ -658,4 +659,20 @@ void main() { ...@@ -658,4 +659,20 @@ void main() {
debugSemanticsDisableAnimations = null; debugSemanticsDisableAnimations = null;
}); });
}); });
test('AnimationController methods assert _ticker is not null', () {
final AnimationController controller = AnimationController(
vsync: const TestVSync(),
);
controller.dispose();
expect(() => controller.animateBack(0), throwsAssertionError);
expect(() => controller.animateTo(0), throwsAssertionError);
expect(() => controller.animateWith(GravitySimulation(0, 0, 0, 0)), throwsAssertionError);
expect(() => controller.stop(), throwsAssertionError);
expect(() => controller.forward(), throwsAssertionError);
expect(() => controller.reverse(), throwsAssertionError);
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment