Flutter. New Disposer widget

Yuriy NovikovYuriy Novikov
3 min read

https://medium.com/easy-flutter/flutter-new-disposer-widget-681eeda1d9ba?sk=897c7c95919a335517e22099e8808586

1. Introduction

Almost every Flutter app has a form with text fields.

The text field requires TextEditingConroller.

TextEditingController has a dispose() method. Therefore we need a StatefulWidget just to dispose of a TextEditingController.

Stateful widgets are verbose, hardly readable, not performance-friendly, and violate several software development principles.

2. An example of resources disposal using StatefulWidget

class Test extends StatefulWidget {
  @override
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> {
  TextEditingController controller;
  FocusNode focusNode;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Disposer Example View'),
        centerTitle: true,
      ),
      body: Center(
        child: Container(
          child: TextField(
            focusNode: focusNode,
            controller: controller,
          ),
        ),
      ),
    );
  }

  @override
  void initState() {
    controller = TextEditingController();
    focusNode = FocusNode();
    super.initState();
  }

  @override
  void dispose() {
    controller.dispose();
    focusNode.dispose();
    super.dispose();
  }
}

It would be much better if we just use StatelessWidget instead.

Here are several questions on Stackoverflow which raise the same problem:

Is it okay to use TextEditingController in StatelessWidget in Flutter?
I don't need to do many things with TextEditingController but want to show the initial text. And I feel like creating…stackoverflow.com

Using controllers inside StatelessWidget
Normally we dispose all controllers in StatefulWidget's dispose method. But how if we are using StatelessWidget? is…stackoverflow.com

The problem, obviously, is not limited to the TextEditingController, it is also animation controllers, subscriptions to steams, timers, and any Dart objects with the dispose() method.

All of them require StatefulWidgets, but we would rather use StatelessWidget instead.

But we cannot since StatelessWidget doesn’t have the dispose() method.

And here the Disposer widget comes as a savior.

3. An example of resources disposal using StatelessWidget with a Disposer

class DisposerExampleView extends StatelessWidget {
  DisposerExampleView({super.key});

  TextEditingController controller = TextEditingController();
  FocusNode focusNode = FocusNode();

  void dispose() {         //here
    controller.dispose();
    focusNode.dispose();
    print('controller and focusNode were disposed');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Disposer Example View'),
        centerTitle: true,
      ),
      body: Center(
          child: Column(
        children: [
          TextField(
            focusNode: focusNode,
            controller: controller,
          ),
          Disposer(dispose: dispose),  //and here
        ],
      )),
    );
  }
}

We just wrote the dispose method and supplied it to Disposer widget’s dispose property.

And, voila, we don’t need StatefulWidget anymore. Our code became shorter and more readable.

So, where does the Disposer widget come from?

It comes from nowhere, we need to write it ourselves. But it is really easy to do.

4. Disposer widget implementation

class Disposer extends StatefulWidget {
  final void Function() dispose;
  const Disposer({super.key, required this.dispose});

  @override
  DisposerState createState() {
    return DisposerState();
  }
}

class DisposerState extends State<Disposer> {
  @override
  Widget build(BuildContext context) {
    return SizedBox.shrink();
  }

  @override
  void dispose() {
    widget.dispose();
    super.dispose();
  }
}

We can now include it in our project template somewhere in common/widgets and use it in all projects. I am thinking of publishing it as a package. If you would like to have a package like this, please comment.

5. Conclusion

  • Problem: Many Flutter apps require TextEditingController and other objects that need disposal. This often forces developers to use StatefulWidget, which can be verbose and less performant.

  • Proposed solution: A custom Disposer widget that allows using StatelessWidget while still properly disposing of resources.

  • Benefits of the solution:
    1) Shorter, more readable code
    2) Ability to use StatelessWidget instead of StatefulWidget

0
Subscribe to my newsletter

Read articles from Yuriy Novikov directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Yuriy Novikov
Yuriy Novikov