The point where I got stuck about using autoDispose in Flutter

368 views Asked by At

I would like to discuss about a code. I am using autoDispose in my application but there is a point that confuses me. I am using this autoDispose with ConsumerWidget and I am not sure if it is disposed properly. I am sharing the code below, could you please take a look at it if you have a chance to review the code? Note: I prefer to use ConsumerWidget for efficient performance and I thought I could use autoDispose in this way since I am using riverpod. I used static for security reasons but I am not sure if it causes any issues.

Also, I used ref.onDispose() inside autoDispose, maybe this code is excessive and I already disposed it manually... Thank you in advance for your help...

I am using this autoDispose with ConsumerWidget and I want to make sure that it is properly disposed when dispose() is called.

class ControlTextField extends ConsumerWidget {
  const ControlTextField({super.key});

  static final _textController = Provider.autoDispose<TextEditingController>(
    (ref) {
      final controller = TextEditingController();

      ref.onDispose(() {
        controller.dispose();
      });

      return controller;
    },
  );

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final FocusNode firstFocusNode = FocusNode();
    return Row(
      mainAxisAlignment: MainAxisAlignment.end,
      children: [
        const Icon(Icons.receipt, size: 16),
        const SizedBox(width: 8),
        Expanded(
            flex: 2,
            child: Text('Work List',
                style: Theme.of(context).textTheme.labelMedium)),
        Expanded(
          flex: 2,
          child: SizedBox(
            height: 20,
            child: Consumer(
              builder: (context, watch, _) {
                final textEditingController = ref.watch(_textController);

                return TextField(
                  controller: textEditingController,
                  onChanged: (event) {
                    final textEditingController = ref.read(_textController);

                    debugPrint(textEditingController.value.text);
                  },
                  style: Theme.of(context).textTheme.bodySmall,
                  autocorrect: false,
                  onTapOutside: (b) {
                    FocusManager.instance.primaryFocus?.unfocus();
                  },
                  focusNode: firstFocusNode,
                  enableSuggestions: true,
                  decoration: const InputDecoration(
                    hintText: 'Ara...',
                    suffixIcon: Icon(Icons.search, size: 12),
                  ),
                  keyboardType: TextInputType.text,
                  autofocus: false,
                  inputFormatters: <TextInputFormatter>[
                    FilteringTextInputFormatter.singleLineFormatter
                  ],
                );
              },
            ),
          ),
        ),
      ],
    );
  }
}
1

There are 1 answers

2
Ruble On

Exactly for these purposes, you can use a couple of packages:

And your code will look like this:

class ControlTextField extends HookConsumerWidget {
  const ControlTextField({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final firstFocusNode = useFocusNode();
    final textEditingController = useTextEditingController();
    
    // .. lots of other code
    return TextField(
      controller: textEditingController,
      onChanged: (event) {
        // do something
        
        debugPrint(textEditingController.text);
      },
      onTapOutside: (_) {
        FocusScope.of(context).unfocus();
      },
      focusNode: firstFocusNode,
    );
  }
}

In this case, we are using the HookConsumerWidget class, which allows the use of hooks in the build method. Hooks are things that will be disposed of on their own if necessary. Also, you can add some parameters to useTextEditingController.fromValue(...), such as initial text.

I also changed your FocusNode object, which also needs to be properly disposed of.


If you don't like hooks for whatever reason, use the ConsumerStatefulWidget widget and the initState() and dispose() methods to define any of your controllers and dispose of them afterwards. This way you better show your intentions in the code.