dispose_fields
v0.4.0 Warning Fix Resource Management
Flags instance fields in State subclasses whose type has a dispose(), close(), or cancel() method but the field is not cleaned up in the widget’s dispose() method. Common types include TextEditingController, FocusNode, AnimationController, StreamController, StreamSubscription, and Timer.
Why use this rule
Section titled “Why use this rule”Disposable resources that are not cleaned up cause memory leaks. A TextEditingController that is never disposed keeps its listeners and internal state alive indefinitely. This rule checks that every field with a cleanup method has a matching call in dispose(), catching missing or incomplete cleanup.
See also: State.dispose()
class _BadState extends State<BadWidget> { final _textController = TextEditingController(); final _focusNode = FocusNode(); final _streamController = StreamController<int>();
// No dispose() method -- all fields leak
@override Widget build(BuildContext context) => const SizedBox();}
class _IncompleteState extends State<IncompleteWidget> { final _controller1 = TextEditingController(); final _controller2 = TextEditingController();
@override void dispose() { _controller1.dispose(); // _controller2 is missing! super.dispose(); }
@override Widget build(BuildContext context) => const SizedBox();}class _GoodState extends State<GoodWidget> { final _textController = TextEditingController(); final _focusNode = FocusNode();
@override void dispose() { _textController.dispose(); _focusNode.dispose(); super.dispose(); }
@override Widget build(BuildContext context) => const SizedBox();}
class _StreamState extends State<StreamWidget> { final _streamController = StreamController<int>();
@override void dispose() { _streamController.close(); super.dispose(); }
@override Widget build(BuildContext context) => const SizedBox();}Configuration
Section titled “Configuration”To disable this rule:
plugins: many_lints: diagnostics: dispose_fields: false