-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Fix(AnimatedScrollView): exclude outgoing items in removeAllItems #176452
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
Fix(AnimatedScrollView): exclude outgoing items in removeAllItems #176452
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
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 fixes a bug in AnimatedList where an exception could be thrown if removeAllItems was called while other items were already undergoing a removal animation. The fix correctly calculates the range of items to remove by excluding items that are already animating out. My review includes suggestions to improve the clarity of a variable name and the documentation for the removeAllItems method.
The `removeAllItems` method now correctly calculates the range of items to remove, excluding those already undergoing a removal animation. This prevents an assert from triggering when `removeAllItems` is called while other items are still being removed.
acf6820 to
b6582e0
Compare
|
@chunhtai @chinmaygarde can I ask for review? |
|
@Piinks what should I do to accelerate this process of review? |
justinmc
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.
Can you add a test for this?
Adds a test case to ensure that calling `removeAllItems` on an `AnimatedList` while another item is already in the process of being removed executes safely and correctly clears the list.
|
@justinmc added test for the exact scenario that I am testing. Waiting for review |
justinmc
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 with nits 👍
…mentation The documentation for `AnimatedList.removeAllItems` is clarified to better explain its behavior, specifying that it removes all items, including those being inserted, but excludes those already being removed. The implementation is updated to use a more descriptive variable name, `visibleItemCount`, for better code readability. Additionally, periods have been added to comments in the corresponding test file for grammatical correctness.
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
|
autosubmit label was removed for flutter/flutter/176452, because - The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
Can't tell whats wrong from google test log, rerun to see if it passes |
justinmc
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, will autosubmit
Roll Flutter from 2d3416713fe8 to 75004a639ae4 (39 revisions) flutter/flutter@2d34167...75004a6 2025-10-22 [email protected] [Impeller] Add the paint color to the key of the text shadow cache (flutter/flutter#177140) 2025-10-22 [email protected] Roll Skia from 96e75ca8e24b to 928b5cf727c1 (2 revisions) (flutter/flutter#177387) 2025-10-22 [email protected] Roll reclient to version 185 (flutter/flutter#177293) 2025-10-22 [email protected] Roll Skia from b157f6b95f95 to 96e75ca8e24b (4 revisions) (flutter/flutter#177366) 2025-10-22 [email protected] Fix InputDatePickerFormField does not inherit local InputDecorationTheme (flutter/flutter#177090) 2025-10-22 [email protected] Roll Skia from 2c6162c977db to b157f6b95f95 (2 revisions) (flutter/flutter#177362) 2025-10-22 [email protected] Roll Skia from cadf8e7e6fca to 2c6162c977db (4 revisions) (flutter/flutter#177359) 2025-10-22 [email protected] Cleanup after -news_toolkit, +google_fonts, and some leftover `team-go_router` (flutter/flutter#176841) 2025-10-21 [email protected] don't break sheet's snap from physics (flutter/flutter#171157) 2025-10-21 [email protected] Roll Dart SDK from 913c2ae1b367 to c23010c4f9e6 (8 revisions) (flutter/flutter#177348) 2025-10-21 [email protected] Fix typo in comment about screen availibility (flutter/flutter#177168) 2025-10-21 [email protected] Fix(AnimatedScrollView): exclude outgoing items in removeAllItems (flutter/flutter#176452) 2025-10-21 [email protected] Enable deprecated_member_use_from_same_package for all packages containing tests of Dart fixes defined within the package (flutter/flutter#177341) 2025-10-21 [email protected] Roll Skia from 19bff385f7e8 to cadf8e7e6fca (3 revisions) (flutter/flutter#177331) 2025-10-21 [email protected] Revert "[Android 16] Update `android_engine_vulkan_tests` to Test Against SDK 36 Emulator" (flutter/flutter#177292) 2025-10-21 [email protected] Fix SliverMainAxisGroup.cacheOrigin (flutter/flutter#175760) 2025-10-21 [email protected] Roll Skia from 75c756e029c9 to 19bff385f7e8 (3 revisions) (flutter/flutter#177316) 2025-10-21 [email protected] Fix typo in overlay.dart documentation comment (flutter/flutter#176612) 2025-10-21 [email protected] [ Tool ] Output DTD URI for Flutter web applications (flutter/flutter#177310) 2025-10-21 [email protected] Roll Skia from 982988b472a4 to 75c756e029c9 (1 revision) (flutter/flutter#177305) 2025-10-21 [email protected] Roll Skia from 42ff13a91c80 to 982988b472a4 (8 revisions) (flutter/flutter#177300) 2025-10-21 [email protected] Fix DateRangePickerDialog does not inherit local InputDecorationTheme (flutter/flutter#177086) 2025-10-21 [email protected] Remove references to dart:_js_annotations (flutter/flutter#176698) 2025-10-20 [email protected] Make `FlutterSceneLifeCycleProvider.sceneLifeCycleDelegate` readonly (flutter/flutter#177240) 2025-10-20 [email protected] Make sure that a CupertinoDesktopTextSelectionToolbar doesn't crash i… (flutter/flutter#173964) 2025-10-20 [email protected] Make sure that a BottomSheet doesn't crash in 0x0 environment (flutter/flutter#172229) 2025-10-20 [email protected] Move the Fuchsia SDK to //third_party/fuchsia-sdk (flutter/flutter#177118) 2025-10-20 [email protected] Roll Skia from 641994569415 to 42ff13a91c80 (8 revisions) (flutter/flutter#177283) 2025-10-20 [email protected] Make sure that a NavigationDrawer doesn't crash in 0x0 environment (flutter/flutter#176951) 2025-10-20 [email protected] Fix ink features painting in TabBar. (flutter/flutter#177155) 2025-10-20 [email protected] Make sure that SimpleDialog and SimpleDialogOption do not crash in 0x0 environment (flutter/flutter#174229) 2025-10-20 [email protected] Fix ink features painting in YearPicker. (flutter/flutter#177014) 2025-10-20 [email protected] Update `image.error_builder.0.dart` to replace the emoji with some text (flutter/flutter#176886) 2025-10-20 [email protected] Roll Skia from ed4294faecde to 641994569415 (4 revisions) (flutter/flutter#177264) 2025-10-20 [email protected] Remove redundant name field form `TargetPlatform` and `XCDeviceEventInterface` enums (flutter/flutter#176890) 2025-10-20 [email protected] Added support to pass in texture type while creating textures. (flutter/flutter#175376) 2025-10-20 [email protected] Roll Packages from 3747006 to d113bbc (6 revisions) (flutter/flutter#177270) 2025-10-20 [email protected] Roll Dart SDK from 2cd2106f2cef to 913c2ae1b367 (2 revisions) (flutter/flutter#177258) 2025-10-20 [email protected] Added link to ClipRect from ImageFilter in the docstring (flutter/flutter#177196) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. ...
…utter#176452) <!-- Thanks for filing a pull request! Reviewers are typically assigned within a week of filing a request. To learn more about code review, see our documentation on Tree Hygiene: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md --> Fix: flutter#176362 Issue provided reproducible code related to exception being thrown when removing all items in an `AnimatedList` when some of the item were already being removed but had a long animation duration. In this PR: The `removeAllItems` method now correctly calculates the range of items to remove, excluding those already undergoing a removal animation. This prevents an assert from triggering when `removeAllItems` is called while other items are still being removed. <details open> <summary> Video example after fix </summary> https://github.com/user-attachments/assets/c7351702-b829-4e35-9978-b95f9f3ae8cd </details> <details open> <summary> Updated reproducible code </summary> ``` import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @OverRide Widget build(BuildContext context) { return const MaterialApp(debugShowCheckedModeBanner: false, home: AnimatedListExample()); } } class AnimatedListExample extends StatefulWidget { const AnimatedListExample({super.key}); @OverRide State<AnimatedListExample> createState() => _AnimatedListExampleState(); } class _AnimatedListExampleState extends State<AnimatedListExample> { final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>(); final List<int> _items = List<int>.generate(10, (int index) => index); void _removeItem(int index) { final int removedItem = _items[index]; _listKey.currentState?.removeItem( index, (BuildContext context, Animation<double> animation) => SizeTransition( sizeFactor: animation, child: _buildItem(removedItem, animation, isRemoved: true), ), // 👇 Long delay so you can press "Remove All" while it’s still animating duration: const Duration(seconds: 10), ); _items.removeAt(index); } void _addItem() { final int addingItem = _items.length; _listKey.currentState?.insertItem(addingItem, duration: const Duration(seconds: 3)); _items.add(addingItem); } void _removeAll() { _listKey.currentState?.removeAllItems((BuildContext context, Animation<double> animation) { return SizeTransition( sizeFactor: animation, child: Container( color: Colors.red[100], child: const ListTile(title: Text('Removing...')), ), ); }, duration: const Duration(seconds: 2)); _items.clear(); } Widget _buildItem(int item, Animation<double> animation, {bool isRemoved = false}) { return SizeTransition( sizeFactor: animation, child: Card( margin: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), child: ListTile( title: Text('Item $item'), trailing: !isRemoved ? IconButton( icon: const Icon(Icons.delete, color: Colors.red), onPressed: () { final int index = _items.indexOf(item); if (index != -1) { _removeItem(index); } }, ) : null, ), ), ); } @OverRide Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('AnimatedList Example'), actions: <Widget>[ TextButton(onPressed: _addItem, child: const Text('Add')), TextButton( onPressed: _items.isNotEmpty ? _removeAll : null, child: const Text('Clear list'), ), ], ), body: AnimatedList( key: _listKey, initialItemCount: _items.length, itemBuilder: (BuildContext context, int index, Animation<double> animation) { return _buildItem(_items[index], animation); }, ), ); } } ``` </details> ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. 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](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot 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. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: chunhtai <[email protected]>
Fix: #176362
Issue provided reproducible code related to exception being thrown when removing all items in an
AnimatedListwhen some of the item were already being removed but had a long animation duration.In this PR: The
removeAllItemsmethod now correctly calculates the range of items to remove, excluding those already undergoing a removal animation. This prevents an assert from triggering whenremoveAllItemsis called while other items are still being removed.Video example after fix
Screen.Recording.2025-10-03.at.12.45.34.PM.mov
Updated reproducible code
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.