setState() 在 dispose() 之后调用
setState() called after dispose()
当我点击凸起的按钮时,时间选择器出现了。现在,如果我等待 5 秒,然后确认时间,就会出现这个错误:
setState() 在 dispose() 之后调用
我确实在控制台中看到 flutter 如何更新父小部件,但为什么呢?我什么都不做-我只等了 5 秒钟?!
下面的示例将在普通项目中工作,但是在我的项目中它更复杂它不会工作,因为 Flutter 在我等待时更新状态......我做错了什么?有没有人猜到 Flutter 在我的更复杂的项目中而不是在一个简单的项目中随机更新是什么?
[更新]
我再次查看它,发现它正在从我的 TabBar
和 TabBarView
所在的级别更新。
它是否必须对 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> {
....
}
当我点击凸起的按钮时,时间选择器出现了。现在,如果我等待 5 秒,然后确认时间,就会出现这个错误: setState() 在 dispose() 之后调用
我确实在控制台中看到 flutter 如何更新父小部件,但为什么呢?我什么都不做-我只等了 5 秒钟?! 下面的示例将在普通项目中工作,但是在我的项目中它更复杂它不会工作,因为 Flutter 在我等待时更新状态......我做错了什么?有没有人猜到 Flutter 在我的更复杂的项目中而不是在一个简单的项目中随机更新是什么?
[更新]
我再次查看它,发现它正在从我的 TabBar
和 TabBarView
所在的级别更新。
它是否必须对 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()
.
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> {
....
}