Skip to content

Failure to manage listener lifecycles correctly #58334

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

Open
jacob314 opened this issue Feb 28, 2021 · 0 comments
Open

Failure to manage listener lifecycles correctly #58334

jacob314 opened this issue Feb 28, 2021 · 0 comments
Labels
area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages. customer-flutter devexp-linter Issues with the analyzer's support for the linter package linter-lint-request P3 A lower priority bug or feature request type-enhancement A request for a change that isn't a bug

Comments

@jacob314
Copy link
Member

Describe the issue
StatefulWidget classes sometimes adds event listeners but fails to remove them. This results in memory leaks if the valueListenable lifecycle is significantly longer than the widget. These bugs are hard for users to catch as everything seems fine they are just leaking memory. These memory leaks could also be detected by runtime tools but is preferable to catch them with static analysis if we can do it without false positives.

To start with, we should focus on only Listenable (and subclasses) but this also applies to streams and many other listenable objects in Dart.

Every listener added manually needs to be removed typically in the dispose method.
If listeners are added in didUpdateWidget or updateDependencies then they also need to be removed from those methods as otherwise widgets end up with multiple listeners.

To Reproduce

void initState() {
  super.initState();
  widget.valueListenable.addListener(myListener);
}

didUpdateWidget(MyWidget oldWidget) {
  if (oldWidget.valueListenable != widget.valueListenable) {
    widget.valueListenable.addListener(myListener);
    oldWidget.valueListenable.removeListener(myListener); // error if this line is removed.
  }
}

void dispose() {
  widget.valueListenable.removeListener(myListener); // Error if this is omitted.
  super.dispose();
}

Expected behavior
Expect warnings for cases where a State object is never removing listeners it is adding.

Additional context
Memory leaks can be significant problem for Flutter applications that manually add and remove listeners as it is easy to get the lifecycle wrong as it is manual.

@pq pq added customer-flutter linter-lint-request type-enhancement A request for a change that isn't a bug labels Mar 5, 2021
@devoncarew devoncarew added devexp-linter Issues with the analyzer's support for the linter package legacy-area-analyzer Use area-devexp instead. labels Nov 19, 2024
@devoncarew devoncarew transferred this issue from dart-archive/linter Nov 19, 2024
@pq pq added the P3 A lower priority bug or feature request label Nov 20, 2024
@bwilkerson bwilkerson added area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages. and removed legacy-area-analyzer Use area-devexp instead. labels Feb 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages. customer-flutter devexp-linter Issues with the analyzer's support for the linter package linter-lint-request P3 A lower priority bug or feature request type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

4 participants