setState() 在 dispose() 之后调用

setState() called after dispose()

当我点击凸起的按钮时,时间选择器出现了。现在,如果我等待 5 秒,然后确认时间,就会出现这个错误: setState() 在 dispose() 之后调用

我确实在控制台中看到 flutter 如何更新父小部件,但为什么呢?我什么都不做-我只等了 5 秒钟?! 下面的示例将在普通项目中工作,但是在我的项目中它更复杂它不会工作,因为 Flutter 在我等待时更新状态......我做错了什么?有没有人猜到 Flutter 在我的更复杂的项目中而不是在一个简单的项目中随机更新是什么?

[更新] 我再次查看它,发现它正在从我的 TabBarTabBarView 所在的级别更新。 它是否必须对 TabBarView 所需的“with TickerProviderStateMixin”做些什么?会不会是导致app定时随机刷新?

 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();
      }
    );
  }
}

如果 Future 在处理小部件时完成是预期的行为,您可以使用

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

试试这个

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

在调用 setState().

之前,只需检查小部件状态 class 的布尔值 属性 mounted
if (this.mounted) {
  setState(() {
    // Your state change code goes here
  });
}

或者更干净的方法 在 StatelfulWidget class.

中覆盖 setState 方法
class DateTimeButton extends StatefulWidget {
  @override
  void setState(fn) {
    if(mounted) {
      super.setState(fn);
    }
  }
}

setState()

前写一行
 if (!mounted) return;

然后是

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

我遇到了同样的问题,我解决了在 initState() 上更改超级构造函数调用顺序的问题:

错误代码:

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

正确的代码:

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

为了防止错误发生,可以使用mounted 属性 或 State class 来确保在设置它之前挂载一个小部件状态:

// First Update data 

if (!mounted) { 
      return;
 }
setState(() { }
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);
    }
  }
}

例子

为了防止错误,而不是使用状态使用 MountedState

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

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

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