-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Do not dispose CupertinoSheetTransition animation on update and throw ticker error #180609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request correctly fixes a ticker-related exception in CupertinoSheetTransition by adjusting the lifecycle of _stretchDragController. Moving its initialization to initState and disposal to dispose is the right approach to prevent issues during widget updates. The new test case provides good coverage for the fix. I have one suggestion to clean up some unused code in the test file.
| class _RebuildingPage extends StatefulWidget { | ||
| const _RebuildingPage({required this.scaffoldKey}); | ||
|
|
||
| final GlobalKey scaffoldKey; | ||
|
|
||
| @override | ||
| _RebuildingPageState createState() => _RebuildingPageState(); | ||
| } | ||
|
|
||
| class _RebuildingPageState extends State<_RebuildingPage> { | ||
| late int counter; | ||
|
|
||
| @override | ||
| void initState() { | ||
| super.initState(); | ||
| counter = 0; | ||
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return CupertinoApp( | ||
| home: CupertinoPageScaffold( | ||
| key: widget.scaffoldKey, | ||
| child: Center( | ||
| child: Column( | ||
| children: <Widget>[ | ||
| const Text('Page 1'), | ||
| CupertinoButton( | ||
| onPressed: () { | ||
| Navigator.push<void>( | ||
| widget.scaffoldKey.currentContext!, | ||
| CupertinoSheetRoute<void>( | ||
| builder: (BuildContext context) { | ||
| return CupertinoPageScaffold( | ||
| child: Center( | ||
| child: Column( | ||
| children: <Widget>[ | ||
| const Text('Page two'), | ||
| Text('Counter Value: $counter'), | ||
| CupertinoButton( | ||
| onPressed: () => setState(() { | ||
| counter++; | ||
| }), | ||
| child: const Text('Increase Count'), | ||
| ), | ||
| ], | ||
| ), | ||
| ), | ||
| ); | ||
| }, | ||
| ), | ||
| ); | ||
| }, | ||
| child: const Text('Push Page 2'), | ||
| ), | ||
| ], | ||
| ), | ||
| ), | ||
| ), | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| final newAnimation = AnimationController(vsync: const TestVSync()); | ||
|
|
||
| // Should not throw an exception. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drive by nit, we can probably assert this with expect(tester.takeException(), isNull);
since otherwise this would throw an AssertionError ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
chunhtai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, except for minor comments
| reverseCurve: Curves.easeInToLinear, | ||
| parent: widget.secondaryRouteAnimation, | ||
| ); | ||
| _stretchDragController = AnimationController( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we do a _stretchDragController.reset() here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. I don't see a need to reseting the value and casing the jump on this update flow. I'd think we would want to hold the old status and value if it's non-zero.
|
|
||
| final newAnimation = AnimationController(vsync: const TestVSync()); | ||
|
|
||
| // Should not throw an exception. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
d09bdbd to
75fc3cd
Compare
…nd throw ticker error (flutter/flutter#180609)
…nd throw ticker error (flutter/flutter#180609)
…nd throw ticker error (flutter/flutter#180609)
…nd throw ticker error (flutter/flutter#180609)
…nd throw ticker error (flutter/flutter#180609)
… and throw ticker error (flutter/flutter#180609)
…nd throw ticker error (flutter/flutter#180609)
…nd throw ticker error (flutter/flutter#180609)
…nd throw ticker error (flutter/flutter#180609)
…nd throw ticker error (flutter/flutter#180609)
…nd throw ticker error (flutter/flutter#180609)
Fixes #179337 by moving the disposal of an animation controller outside of the didUpdate method flow. It was unnecessary to rebuild this controller on update, and was originally put there to follow the pattern of the other animations. However, unlike the other animations, this one is not chained to animations from outside of the transition's place in the tree, and was throwing exceptions from the ticker mixin in some cases.
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.