在释放()之后调用 setState()

当我点击凸起的按钮时,计时器就会显示出来。现在,如果我等待5秒钟,然后确认时间,这个错误就会发生: 在释放()之后调用 setState ()

我确实在控制台中看到了如何更新父窗口小部件,但是为什么呢?- 我什么都没做-我就等5秒钟? ! 下面的例子将工作在一个正常的项目,但是在我的项目,这是相当复杂的,它不会工作,因为扑动是更新状态,而我在等待... 我做错了什么?有没有人猜一猜,在我的更复杂的项目中,而不是在一个简单的项目中,Flutter 正在随机更新的可能是什么?

我看了第二次,发现它是从我的 TabBarTabBarView的水平更新。 它可以做一些与“ 使用 ticerProviderStateMixin”,我需要的 TabBarView?会不会是它导致应用程序定期随机刷新?

 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();
}
);
}
}
92323 次浏览

如果 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类中重写 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
}

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

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

例子

若要防止错误,请使用 加州骑警代替使用 State

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


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


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

当我在变量之前错误地调用 super.initState 时出现了这个错误:

@override
void initState() {
super.initState();
bloc = MainBloc();
}

应该定为

@override
void initState() {
bloc = MainBloc();
super.initState();
}

上面的答案也是正确的,但是根据文档 < img src = “ https://i.stack.imgur.com/dbEzK.png”alt = “ enter image description here”/> < img src = “ https://i.stack.imgur.com/dbEzK.png”alt = “在这里输入图像描述”/> 的解释是,

此[ State ]对象当前是否在树中。 在创建[ State ]对象并调用[ initState ]之前, 框架“ 坐骑”通过将[ State ]对象与 [ BuildContext ] . [ State ]对象一直挂载到框架 调用[释放] ,此后框架将永远不会要求[状态] 再次构建的对象。 除非[ 安装]为 true,否则调用[ setState ]是错误的。

简单来说,setState 在几个地方等待之后被调用,解决方案可能很简单,只需添加一个约束,这样在丢弃小部件之后就不会调用它,例如:

 if (mounted){
setState(() {
// your code
});
}