setState() called after dispose()

Flutter

Flutter Problem Overview


When I click the raised button, the timepicker is showing up. Now, if I wait 5 seconds, for example, and then confirm the time, this error will occur: setState() called after dispose()

I literally see in the console how flutter is updating the parent widgets, but why? I don't do anything - I just wait 5 seconds?! The example below will work in a normal project, however in my project which is quite more complex it won't work because Flutter is updating the states while I am waiting... What am I doing wrong? Does anyone have a guess at what it could be that Flutter is updating randomly in my more complex project and not in a simple project?

[UPDATE] I took a second look at it and found out it is updating from the level on where my TabBar and TabBarView are. Could it have to do something with the "with TickerProviderStateMixin" which I need for the TabBarView? Could it be that it causes the app to refresh regularly and randomly?

 class DateTimeButton extends State<DateTimeButtonWidget> {
  DateTime selectedDate = new DateTime.now();

  Future initTimePicker() async {
    final TimeOfDay picked = await showTimePicker(
      context: context,
      initialTime: new TimeOfDay(hour: selectedDate.hour, minute: selectedDate.minute),
    );

    if (picked != null) {
      setState(() {
        selectedDate = new DateTime(selectedDate.year, selectedDate.month, selectedDate.day, picked.hour, picked.minute);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return new RaisedButton(
      child: new Text("${selectedDate.hour} ${selectedDate.minute}"),
      onPressed: () {
        initTimePicker();
      }
    );
  }
}

Flutter Solutions


Solution 1 - Flutter

Just check boolean property mounted of the state class of your widget before calling setState().

if (this.mounted) {
  setState(() {
    // Your state change code goes here
  });
}

Or even more clean approach Override setState method in your StatelfulWidget class.

class DateTimeButton extends StatefulWidget {
  @override
  void setState(fn) {
    if(mounted) {
      super.setState(fn);
    }
  }
}

Solution 2 - Flutter

If it is an expected behavior that the Future completes when the widget already got disposed you can use

if (mounted) {
  setState(() {
    selectedDate = new DateTime(selectedDate.year, selectedDate.month, selectedDate.day, picked.hour, picked.minute);
  });
}

Solution 3 - Flutter

Just write one line before setState()

 if (!mounted) return;

and then

setState(() {
      //Your code
    });

Solution 4 - Flutter

I had the same problem and i solved changing the super constructor call order on initState():

Wrong code:

@override
  void initState() {
    foo_bar(); // call setState();
    super.initState(); // then foo_bar()
  }

Right code:

@override
  void initState() {
    super.initState();
    foo_bar(); // first call super constructor then foo_bar that contains setState() call
  }

Solution 5 - Flutter

To prevent the error from occurring, one can make use of the mounted property of the State class to ensure that a widget is mounted before settings its state:

// First Update data 

if (!mounted) { 
      return;
 }
setState(() { }

Solution 6 - Flutter

Try this

Widget build(BuildContext context) {
    return new RaisedButton(
        child: new Text("${selectedDate.hour} ${selectedDate.minute}"),
        onPressed: () async {
            await initTimePicker();
        }
    );
}

Solution 7 - Flutter

class MountedState<T extends StatefulWidget> extends State<T> {
  @override
  Widget build(BuildContext context) {
    return null;
  }

  @override
  void setState(VoidCallback fn) {
    if (mounted) {
      super.setState(fn);
    }
  }
}

Example

To prevent the error,Instead of using State use MountedState

class ExampleStatefulWidget extends StatefulWidget {
  const ExampleStatefulWidget({Key key}) : super(key: key);

  @override
  _ExampleStatefulWidgetState createState() => _ExampleStatefulWidgetState();
}

class _ExampleStatefulWidgetState extends MountedState<ExampleStatefulWidget> {
  ....
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGreenTigerEyeView Question on Stackoverflow
Solution 1 - FlutterGanapatView Answer on Stackoverflow
Solution 2 - FlutterGünter ZöchbauerView Answer on Stackoverflow
Solution 3 - FlutterRahul MahadikView Answer on Stackoverflow
Solution 4 - FlutterteteArgView Answer on Stackoverflow
Solution 5 - FlutterDimarBordaView Answer on Stackoverflow
Solution 6 - FlutterPrimeNexesView Answer on Stackoverflow
Solution 7 - Flutterkarzan kamalView Answer on Stackoverflow