Unverified Commit 7f17cf45 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Cheaper debug string for widget-provided tickers (#81247)

parent d1f02ae0
...@@ -126,7 +126,7 @@ mixin SingleTickerProviderStateMixin<T extends StatefulWidget> on State<T> imple ...@@ -126,7 +126,7 @@ mixin SingleTickerProviderStateMixin<T extends StatefulWidget> on State<T> imple
), ),
]); ]);
}()); }());
_ticker = Ticker(onTick, debugLabel: kDebugMode ? 'created by $this' : null); _ticker = Ticker(onTick, debugLabel: kDebugMode ? 'created by ${describeIdentity(this)}' : null);
// We assume that this is called from initState, build, or some sort of // We assume that this is called from initState, build, or some sort of
// event handler, and that thus TickerMode.of(context) would return true. We // event handler, and that thus TickerMode.of(context) would return true. We
// can't actually check that here because if we're in initState then we're // can't actually check that here because if we're in initState then we're
...@@ -199,7 +199,7 @@ mixin TickerProviderStateMixin<T extends StatefulWidget> on State<T> implements ...@@ -199,7 +199,7 @@ mixin TickerProviderStateMixin<T extends StatefulWidget> on State<T> implements
@override @override
Ticker createTicker(TickerCallback onTick) { Ticker createTicker(TickerCallback onTick) {
_tickers ??= <_WidgetTicker>{}; _tickers ??= <_WidgetTicker>{};
final _WidgetTicker result = _WidgetTicker(onTick, this, debugLabel: 'created by $this'); final _WidgetTicker result = _WidgetTicker(onTick, this, debugLabel: kDebugMode ? 'created by ${describeIdentity(this)}' : null);
_tickers!.add(result); _tickers!.add(result);
return result; return result;
} }
......
...@@ -117,7 +117,7 @@ void main() { ...@@ -117,7 +117,7 @@ void main() {
'the ticker will leak.\n' 'the ticker will leak.\n'
); );
expect(error.diagnostics[3], isA<DiagnosticsProperty<Ticker>>()); expect(error.diagnostics[3], isA<DiagnosticsProperty<Ticker>>());
expect(error.toStringDeep().split('\n').take(14).join('\n'), equalsIgnoringHashCodes( expect(error.toStringDeep().split('\n').take(13).join('\n'), equalsIgnoringHashCodes(
'FlutterError\n' 'FlutterError\n'
' _SingleTickerTestState#00000(ticker active) was disposed with an\n' ' _SingleTickerTestState#00000(ticker active) was disposed with an\n'
' active Ticker.\n' ' active Ticker.\n'
...@@ -129,8 +129,7 @@ void main() { ...@@ -129,8 +129,7 @@ void main() {
' calling dispose() on the AnimationController itself. Otherwise,\n' ' calling dispose() on the AnimationController itself. Otherwise,\n'
' the ticker will leak.\n' ' the ticker will leak.\n'
' The offending ticker was:\n' ' The offending ticker was:\n'
' Ticker(created by _SingleTickerTestState#00000(lifecycle state:\n' ' Ticker(created by _SingleTickerTestState#00000)\n'
' created))\n'
' The stack trace when the Ticker was actually created was:' ' The stack trace when the Ticker was actually created was:'
)); ));
key.currentState!.controller.stop(); key.currentState!.controller.stop();
...@@ -158,7 +157,7 @@ void main() { ...@@ -158,7 +157,7 @@ void main() {
'the ticker will leak.\n' 'the ticker will leak.\n'
); );
expect(error.diagnostics[3], isA<DiagnosticsProperty<Ticker>>()); expect(error.diagnostics[3], isA<DiagnosticsProperty<Ticker>>());
expect(error.toStringDeep().split('\n').take(14).join('\n'), equalsIgnoringHashCodes( expect(error.toStringDeep().split('\n').take(13).join('\n'), equalsIgnoringHashCodes(
'FlutterError\n' 'FlutterError\n'
' _SingleTickerTestState#00000(ticker active) was disposed with an\n' ' _SingleTickerTestState#00000(ticker active) was disposed with an\n'
' active Ticker.\n' ' active Ticker.\n'
...@@ -170,15 +169,14 @@ void main() { ...@@ -170,15 +169,14 @@ void main() {
' calling dispose() on the AnimationController itself. Otherwise,\n' ' calling dispose() on the AnimationController itself. Otherwise,\n'
' the ticker will leak.\n' ' the ticker will leak.\n'
' The offending ticker was:\n' ' The offending ticker was:\n'
' Ticker(created by _SingleTickerTestState#00000(lifecycle state:\n' ' Ticker(created by _SingleTickerTestState#00000)\n'
' created))\n'
' The stack trace when the Ticker was actually created was:' ' The stack trace when the Ticker was actually created was:'
)); ));
key.currentState!.controller.stop(); key.currentState!.controller.stop();
} }
}); });
testWidgets('ProviderStateMixin dispose while any ticker is active', (WidgetTester tester) async { testWidgets('TickerProviderStateMixin dispose while any ticker is active', (WidgetTester tester) async {
final GlobalKey<_MultipleTickerTestState> key = GlobalKey<_MultipleTickerTestState>(); final GlobalKey<_MultipleTickerTestState> key = GlobalKey<_MultipleTickerTestState>();
final Widget widget = _MultipleTickerTest(key: key); final Widget widget = _MultipleTickerTest(key: key);
await tester.pumpWidget(widget); await tester.pumpWidget(widget);
...@@ -199,7 +197,7 @@ void main() { ...@@ -199,7 +197,7 @@ void main() {
'the ticker will leak.\n' 'the ticker will leak.\n'
); );
expect(error.diagnostics[3], isA<DiagnosticsProperty<Ticker>>()); expect(error.diagnostics[3], isA<DiagnosticsProperty<Ticker>>());
expect(error.toStringDeep().split('\n').take(14).join('\n'), equalsIgnoringHashCodes( expect(error.toStringDeep().split('\n').take(12).join('\n'), equalsIgnoringHashCodes(
'FlutterError\n' 'FlutterError\n'
' _MultipleTickerTestState#00000(tickers: tracking 2 tickers) was\n' ' _MultipleTickerTestState#00000(tickers: tracking 2 tickers) was\n'
' disposed with an active Ticker.\n' ' disposed with an active Ticker.\n'
...@@ -211,14 +209,22 @@ void main() { ...@@ -211,14 +209,22 @@ void main() {
' calling dispose() on the AnimationController itself. Otherwise,\n' ' calling dispose() on the AnimationController itself. Otherwise,\n'
' the ticker will leak.\n' ' the ticker will leak.\n'
' The offending ticker was:\n' ' The offending ticker was:\n'
' _WidgetTicker(created by\n' ' _WidgetTicker(created by _MultipleTickerTestState#00000)'
' _MultipleTickerTestState#00000(lifecycle state: created,\n'
' tickers: tracking 0 tickers))'
)); ));
key.currentState!.controllers.first.stop(); key.currentState!.controllers.first.stop();
} }
}); });
}); });
testWidgets('SingleTickerProviderStateMixin does not call State.toString', (WidgetTester tester) async {
await tester.pumpWidget(const _SingleTickerTest());
expect(tester.state<_SingleTickerTestState>(find.byType(_SingleTickerTest)).toStringCount, 0);
});
testWidgets('TickerProviderStateMixin does not call State.toString', (WidgetTester tester) async {
await tester.pumpWidget(const _MultipleTickerTest());
expect(tester.state<_MultipleTickerTestState>(find.byType(_MultipleTickerTest)).toStringCount, 0);
});
} }
class BoringTickerTest extends StatefulWidget { class BoringTickerTest extends StatefulWidget {
...@@ -255,6 +261,14 @@ class _SingleTickerTestState extends State<_SingleTickerTest> with SingleTickerP ...@@ -255,6 +261,14 @@ class _SingleTickerTestState extends State<_SingleTickerTest> with SingleTickerP
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container(); return Container();
} }
int toStringCount = 0;
@override
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
toStringCount += 1;
return super.toString(minLevel: minLevel);
}
} }
class _MultipleTickerTest extends StatefulWidget { class _MultipleTickerTest extends StatefulWidget {
...@@ -279,6 +293,14 @@ class _MultipleTickerTestState extends State<_MultipleTickerTest> with TickerPro ...@@ -279,6 +293,14 @@ class _MultipleTickerTestState extends State<_MultipleTickerTest> with TickerPro
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container(); return Container();
} }
int toStringCount = 0;
@override
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
toStringCount += 1;
return super.toString(minLevel: minLevel);
}
} }
class _SingleTickerCreateMultipleTicker extends StatefulWidget { class _SingleTickerCreateMultipleTicker extends StatefulWidget {
......
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