Repository navigation
[two_dimensional_scrollables] Activate leak testing and fix memory leaks - #11653
auto-submit[bot] merged 18 commits into
Conversation
|
cc @polina-c |
| static Widget builder({ | ||
| Key? key, | ||
| bool? primary, |
There was a problem hiding this comment.
I'm not sure whether that is okay to change from a constructor to a static method. Would you have a better design in mind?
| 'merged column that exceeds metrics will assert', | ||
| // The build throws an assertion error which prevents the table from | ||
| // properly disposing the elements. | ||
| experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), |
There was a problem hiding this comment.
Is it acceptable to have memory leaks when the build asserts?
There was a problem hiding this comment.
Code Review
This pull request updates the two_dimensional_scrollables package to version 0.5.2, focusing on resolving memory leaks by refactoring TableView and TreeView to properly manage the lifecycle of their delegates and animations. It introduces leak_tracker_flutter_testing to the test suite and updates existing tests to ensure proper resource disposal. Review feedback identified several critical issues: missing parameter propagation in the new _TableViewBuilder and _TableViewList widgets, a missing didUpdateWidget implementation in _TableViewListState, and concerns regarding the breaking nature of converting constructors to static methods.
| super.dragStartBehavior, | ||
| super.keyboardDismissBehavior, | ||
| super.clipBehavior, | ||
| static Widget builder({ |
There was a problem hiding this comment.
Changing TableView.builder from a constructor to a static method that returns a Widget is a breaking change. This changes the return type from TableView to Widget, which may break existing code that relies on the specific type or uses it in a context where a TableView instance is expected. Since this is a patch version bump (0.5.1 to 0.5.2), breaking changes should generally be avoided. Consider if a minor version bump is more appropriate or if there is a non-breaking way to manage the delegate's lifecycle.
| ), | ||
| ) | ||
| : TableView.builder( | ||
| key: ValueKey(_selectionMode), |
There was a problem hiding this comment.
I'm doing this to force the widget to rebuild (and re-run _buildCell). Because now, when we toggle from "Single-cell" to "Disable" selection, the delegate doesn't change, and _buildCell is not rebuilt. That makes the test Selection SegmentedButton control works in packages/two_dimensional_scrollables/example/test/table_view/simple_table_test.dart:60 fail.
Ideally, I think we'd need some kind of notifier that the widget built in _buildCell would listen to. But since it is only an example, I'd thought this would be enough?
What do you think?
There was a problem hiding this comment.
Will other users have to apply this change to their existing code? This makes me wonder if this is a breaking change.. might there be performance concerns as well?
There was a problem hiding this comment.
I think I have an idea to mitigate this - instead of caching delegate parameters in TableView and conditionally updating the delegate in TreeView , we should simplify the lifecycle management to avoid correctness bugs (e.g., method tear-offs evaluating to == and blocking cell updates):
- Constructors: Instantiate the delegates directly within the TableView constructors and track if they are internally managed with a final bool _isInternalDelegate flag.
- Disposal: In _TableViewState.didUpdateWidget and dispose , simply check if _isInternalDelegate is true and dispose of the delegate.
- Rebuilding: Remove the parameter caching classes (_TableCellDelegateParameters and subclasses) completely. Always recreate the delegates on rebuilds (including in _TreeViewState.didUpdateWidget ) to ensure parent state changes are correctly propagated to the viewport.
- Revert the key: ValueKey(_selectionMode) workaround in the example application since parent updates will now propagate naturally.
WDYT?
There was a problem hiding this comment.
I'm good with that. What do you think of Do not cache deleguate ? :)
c3f33bf to
6741208
Compare
6741208 to
6d98ff2
Compare
6d98ff2 to
97a29c0
Compare
|
Hey @ValentinVignal thanks for this PR! Sorry I have not finished reviewing it yet. It looks like several checks are failing, can you take a look? |
97a29c0 to
5defacb
Compare
Piinks
left a comment
There was a problem hiding this comment.
Hi @ValentinVignal, thanks again for working on this! Fixing these memory leaks is super important, but I have some concerns about the breaking changes introduced in this PR:
Changing the constructors TableView.builder and TableView.list to static methods returning Widget (instead of TableView) is a breaking change. It breaks code that explicitly types variables as TableView (e.g., TableView table = TableView.builder(...)) and widget tests querying TableView by key.
Instead, I think we can make TableView itself a StatefulWidget that wraps a private stateless _TableViewWidget extending TwoDimensionalScrollView. The state class can manage the lifecycle of internally-created delegates, avoiding any breaking changes or type changes.
Since TreeView is already a StatefulWidget, we can manage the TreeRowBuilderDelegate directly inside the existing _TreeViewState instead of introducing the new private stateful _TreeView widget wrapper.
What do you think about going with this alternative? It allows us to land leak safety without breaking changes or class bloat.
|
@Piinks I updated the PR as per your suggestion. Let me know what you think about it :) |
Piinks
left a comment
There was a problem hiding this comment.
Thanks for the updates @ValentinVignal! It looks like two things still need to be addressed:
- Revert
TableView.builderandTableView.listback to class constructors/factories returningTableViewby makingTableViewitself aStatefulWidget. - Move
TreeRowBuilderDelegatelifecycle management directly into_TreeViewState.
CI appears to be a bit unhappy as well.
f4d60fa to
9b7f1ce
Compare
|
@Piinks There are some merge conflicts if I rebase; I'm trying a merge first to see if it is enough :) |
I understand. Unfortunately we need to rebase this because the base commit is old, which would prevent it from landing. |
# Conflicts: # packages/two_dimensional_scrollables/lib/src/table_view/table.dart
# Conflicts: # packages/two_dimensional_scrollables/CHANGELOG.md
ac32d2c to
ad019f1
Compare
|
@Piinks I have rebased the branch :) |
Piinks
left a comment
There was a problem hiding this comment.
Thank you so much! So excited for this to land!
…er#191965) flutter/packages@bd3cbc1...cd4cdd0 2026-08-28 21270878+elliette@users.noreply.github.com [material_ui] Add all M3 templates and generated code to `temporarily_excluded/` before migration (flutter/packages#12661) 2026-08-28 engine-flutter-autoroll@skia.org Roll Flutter from 15d8908 to e8dca90 (58 revisions) (flutter/packages#12660) 2026-08-28 bkonyi@google.com [various] Update pigeon dev_dependency to ^27.3.2 (flutter/packages#12615) 2026-08-27 269567208+reidbaker-agent@users.noreply.github.com [camera_android_camerax] Enforce CHANGELOG backticks and add eval commit author check to pre-push-skill (flutter/packages#12624) 2026-08-27 imcusg@gmail.com [material_ui] Prevent stale async suggestions in SearchAnchor (flutter/packages#12478) 2026-08-27 bkonyi@google.com [go_router_builder] Support analyzer 14 (flutter/packages#12614) 2026-08-27 srawlins@google.com [cupertino_ui] Use super parameters in more places (flutter/packages#12459) 2026-08-27 32538273+ValentinVignal@users.noreply.github.com [material_ui] Remove no-shuffle from progress indicator test (flutter/packages#12505) 2026-08-27 32538273+ValentinVignal@users.noreply.github.com [two_dimensional_scrollables] Activate leak testing and fix memory leaks (flutter/packages#11653) 2026-08-27 21270878+elliette@users.noreply.github.com [material_ui] Add helper methods in gen_defaults template (flutter/packages#12637) 2026-08-27 brackenavaron@gmail.com [cupertino_ui] fix CupertinoIcons font not being included in examples and fix TextEditingController leaks (flutter/packages#12228) 2026-08-27 269567208+reidbaker-agent@users.noreply.github.com [camera_android_camerax] Check Git hooks configuration in check-readiness skill (flutter/packages#12628) 2026-08-27 47866232+chunhtai@users.noreply.github.com [ci] sync back pr for branch release only run when release succeeds (flutter/packages#12581) 2026-08-27 stuartmorgan@google.com [google_maps_flutter] Convert overlay controllers to Swift (flutter/packages#12638) 2026-08-27 47866232+chunhtai@users.noreply.github.com [go_router_builder] Fixes text golden test to ignore platform specific newline (flutter/packages#12652) 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-flutter-autoroll Please CC flutter-ecosystem@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…aks (flutter#11653) The package manipulates disposable objects. This PR activates leak testing to make sure disposable objects are correctly disposed. It also fixes the memory leak warnings from the tests See the documentation: https://github.com/dart-lang/leak_tracker/blob/main/doc%2Fleak_tracking%2FDETECT.md ## Pre-Review Checklist **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. [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
…aks (flutter#11653) The package manipulates disposable objects. This PR activates leak testing to make sure disposable objects are correctly disposed. It also fixes the memory leak warnings from the tests See the documentation: https://github.com/dart-lang/leak_tracker/blob/main/doc%2Fleak_tracking%2FDETECT.md ## Pre-Review Checklist **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. [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.

The package manipulates disposable objects. This PR activates leak testing to make sure disposable objects are correctly disposed.
It also fixes the memory leak warnings from the tests
See the documentation: https://github.com/dart-lang/leak_tracker/blob/main/doc%2Fleak_tracking%2FDETECT.md
Pre-Review Checklist
[shared_preferences]///).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.Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2