Destroy multiple text editing controllers at once on stateful class exit on Flutter

Viewed 300

I've a scenario where I have to destroy multiple TextEditingController() at the time of dispose() life-cycle hook is called.

StateFull Class

class PersonalDetailsScreen extends StatefulWidget {
  @override
  _PersonalDetailsScreenState createState() => _PersonalDetailsScreenState();
}

class _PersonalDetailsScreenState extends State<PersonalDetailsScreen> {
 final spouseNameController = TextEditingController();
  final fullNameController = TextEditingController();
  final dobController = TextEditingController();
  final fatcaCountryController = TextEditingController();
  final taxIdController = TextEditingController();
  final nomineeNameController = TextEditingController();
  final nomineeDobController = TextEditingController();
  final fatherNameController = TextEditingController();
  final motherNameController = TextEditingController();
  final grossIncomeController = TextEditingController();
  final birthCountryController = TextEditingController();

  // ... 
  // Widget building and other functions in class
  // ...

  @override
  void dispose() {
    spouseNameController.dispose();
    fullNameController.dispose();
    dobController.dispose();
    fatcaCountryController.dispose();
    taxIdController.dispose();
    nomineeNameController.dispose();
    nomineeDobController.dispose();
    fatherNameController.dispose();
    motherNameController.dispose();
    grossIncomeController.dispose();
    birthCountryController.dispose();
    super.dispose();
  }
}

Is there a better way to do this? I thought it might be available in the context but couldn't found.

Thanks

2 Answers

If you use package:hooks_riverpod (https://pub.dev/packages/hooks_riverpod), you can create TextEditingController objects that "autoDispose" and can be created directly in the build() method, rather than having to be set up with initState. (You can even use them in StatelessWidget builds!) It's quite useful, and there are other great things in that package as well. It's from the author of Provider and RiverPod, two indispensable packages.

If you use flutter_hooks your code could look like this:

class PersonalDetailsScreen extends HookWidget {
  const PersonalDetailsScreenState({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final spouseNameController = useTextEditingController();
    final fullNameController = useTextEditingController();
    final dobController = useTextEditingController();
    final fatcaCountryController = useTextEditingController();
    final taxIdController = useTextEditingController();
    final nomineeNameController = useTextEditingController();
    final nomineeDobController = useTextEditingController();
    final fatherNameController = useTextEditingController();
    final motherNameController = useTextEditingController();
    final grossIncomeController = useTextEditingController();
    final birthCountryController = useTextEditingController();
    return Container();
  }
}

As Randal said, these controllers will automatically dispose on their own.

You could also use a map to clean up the build method a bit:

enum DataField {
  spouseName,
  fullName,
  dob,
  fatcaCountry,
  taxId,
  nomineeName,
  nomineeDob,
  fatherName,
  motherName,
  grossIncome,
  birthCountry,
}

class PersonalDetailsScreen extends HookWidget {
  const PersonalDetailsScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final controllerMap = Map.fromEntries(
      DataField.values.map(
        (field) => MapEntry(field, useTextEditingController()),
      ),
    );

    return TextField(controller: controllerMap[DataField.spouseName]);
  }
}
Related