Dispose isn't called when the widgets removed from the window - Flutter

1,268

The reason why dispose() isn't called is because the Screen is still on the Navigation stack. You can remove the current screen by either using Navigator.pop() or Navigator.of(context).pushNamedAndRemoveUntil() - to remove till the specified page and navigate to the next page.

Share:
1,268
Dohan Smit
Author by

Dohan Smit

Updated on December 19, 2022

Comments

  • Dohan Smit
    Dohan Smit over 1 year

    I am using the same stateful widget in 2 different views. It's using a list of TextEditingController that I send as a delegate through

    this is the list of TextControllers :

    var textfieldControllersEx = [
      TextEditingController(),
      TextEditingController(),
      TextEditingController(),
      TextEditingController(),
    ];
    

    the Extracted widget is used twice in 2 different views:

    ExpiryDateTextField(
      controllers: textfieldControllersEx,
      onChangeF: (String value, int i) {
        setState(() {
            _addValuesToAr(value, i);
        });
      },
    ),
    

    on every view I call a dispose and a dispose in the ExpiryDateTextField Function as well with a print to see if it's being disposed:

    It doesn't even call the dispose on either pages

    @override
      void dispose() {
        Print.yellow('DISPOSED');
        textfieldControllersEx[0].dispose();
        textfieldControllersEx[1].dispose();
        textfieldControllersEx[2].dispose();
        textfieldControllersEx[3].dispose();
        textfieldControllersEx[0].text = null;
        textfieldControllersEx[1].text = null;
        textfieldControllersEx[2].text = null;
        textfieldControllersEx[3].text = null;
        // TODO: implement dispose
        super.dispose();
      }
    

    this is the function :

    var focusNodes = [
      FocusNode(),
      FocusNode(),
      FocusNode(),
      FocusNode(),
    ];
    class ExpiryDateTextField extends StatefulWidget {
      final List<TextEditingController> controllers;
      final Function onChangeF;
      ExpiryDateTextField({this.controllers, this.onChangeF});
      @override
      _ExpiryDateTextFieldState createState() => _ExpiryDateTextFieldState();
    }
    class _ExpiryDateTextFieldState extends State<ExpiryDateTextField> {
      @override
      void dispose() {
        // TODO: implement dispose
        super.dispose();
      }
      @override
      Widget build(BuildContext context) {
        bool onSwitchChanged(value, context, index) {
          // print(index++);
          if (index == 4) {
            //if it is on the last text box, do nothing
          } else {
            if (widget.controllers[index].text.length > 0) {
              index++;
              FocusScope.of(context).requestFocus(focusNodes[index]);
              widget.controllers[index].selection = TextSelection(
                baseOffset: 0,
                extentOffset: widget.controllers[index].text.length
              );
              // FocusScope.of(context).focus
            }
          }
          return true;
        }
        return Row(
          children: <Widget>[
            Expanded(
              flex: 1,
              child: SingleDigitTextField(
                onChangedF: (value) {
                  widget.onChangeF(value, 0);
                  print(this.toString(minLevel: DiagnosticLevel.debug));
                  onSwitchChanged(value, context, 0);
                },
                fNode: focusNodes[0],
                cController: widget.controllers[0]
              ),
            ),
            Expanded(
              flex: 1,
              child: SingleDigitTextField(
                onChangedF: (value) {
                  widget.onChangeF(value, 1);
                  onSwitchChanged(value, context, 1);
                },
                fNode: focusNodes[1],
                cController: widget.controllers[1]
              ),
            ),
            Expanded(
              flex: 1,
              child: Text("/",
                textAlign: TextAlign.center,
                style: Theme.of(context).textTheme.display2
              ),
            ),
            Expanded(
              flex: 1,
              child: SingleDigitTextField(
                onChangedF: (value) {
                  widget.onChangeF(value, 2);
                  onSwitchChanged(value, context, 2);
                },
                fNode: focusNodes[2],
                cController: widget.controllers[2]
              ),
            ),
            Expanded(
              flex: 1,
              child: SingleDigitTextField(
                onChangedF: (value) {
                  widget.onChangeF(value, 3);
                  onSwitchChanged(value, context, 3);
                },
                fNode: focusNodes[3],
                cController: widget.controllers[3]
              ),
            ),
          ],
        );
      }
    }
    
    

    this is the error given :

    I/flutter (24293): Another exception was thrown: dependOnInheritedWidgetOfExactType<_ModalScopeStatus>() or dependOnInheritedElement() was called before _ViewState.initState() completed.

    I saw this example but it didn't work because if a value is changed it disposes of the TextControllers immediately :

    @override
      void didChangeDependencies() {
        textfieldControllersEx[0].dispose();
        textfieldControllersEx[1].dispose();
        textfieldControllersEx[2].dispose();
        textfieldControllersEx[3].dispose();
        // TODO: implement didChangeDependencies
        super.didChangeDependencies();
      }
    

    this is how I Navigate :

    Navigator.of(context).pushNamed("/PlaidPage");
    

    Help would be kindly appreciated

    • Manuel
      Manuel about 4 years
      I'm not quite sure, but don't you need a Navigator.of(context).pushNamedAndRemoveUntil("/PlaidPage"); Otherwise the view is still on "behind" on the push/pop stack and the widgets are not disposed
    • Michel Feinstein
      Michel Feinstein about 4 years
      Could you simplify your question with a smaller example? Try creating a new project and just place there the minimum amount of code to reproduce the issue.
    • Dohan Smit
      Dohan Smit about 4 years
      Thanks, @Manuel... I just needed to insert a Navigator.pop(context); before I use Navigator.of(context).pushNamed"/PlaidPage");
    • morgwai
      morgwai almost 3 years
      there's an ongoing discussion regarding this on github. Please voice your support if you think it should be fixed in flutter