Skip to content

Failure to manage listener lifecycles correctly #58334

Open
@jacob314

Description

@jacob314

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3A lower priority bug or feature requestarea-devexpFor issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages.customer-flutterdevexp-linterIssues with the analyzer's support for the linter packagelinter-lint-proposaltype-enhancementA request for a change that isn't a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions