我有以下变量
String _warningMessage;
bool _warningVisibility;
我想通过实现接口的类进行更新
class _UserSignupInterface extends _SignupSelectUsernamePageState
implements UserSignupInterface {
@override
void onSuccess() {
_hideWarning();
_navigateToUserPage();
}
@override
void onError(String message) {
_isSignupClickable = true;
if(message != null) {
_displayWarning(message);
}
}
}
带有_displayWarning代码(位于_SignupSelectUsernamePageState
内)
void _displayWarning(String message) {
if (message != null) {
setState(() {
widget._warningMessage = message;
widget._warningVisibility = true;
});
}
}
但是,每当我从_displayWarning(message)
外部呼叫_SignupSelectUsernamePageState
时。我说错了
Unhandled Exception: setState() called in constructor
是否存在在类之外更新这些变量状态的正确方法?在我的情况下,我正在从实现接口的另一个类中调用_displayWarning(message)
答案 0 :(得分:2)
您必须确定这是在窗口小部件内部内部更改的值,还是在外部对其进行更改的值。
如果是内部的,通常的做法是将它们放在带有{的_上的State
类中,它们可以从initState
上设置的实例值开始,并且每次更改时调用setState
表示这一点。
但是,如果它们在窗口小部件外部更改,则将它们放置在StatefulWidget
类上(就像您所做的一样),因为它们实际上是公共的,所以它们没有_,甚至使它们成为最终的并将它们放在构造函数中以进行设置。
在最后一种情况下,如果必须在State
类中知道小部件中的更改,则可以实现didUpdateWidget
,但这不是强制性的。
当然,您可以混合两种方式,在_warningMessage
中使用State
,因此可以使用setState
进行更新,但要使用initState
中定义的初始值来自小部件。
同样,如果窗口小部件在外部进行了更改,则可以再次使用新的窗口小部件值更新_warningMessage
的值。
类似的东西:(我没有测试这段代码)
class YourWidget extends StatefulWidget {
YourWidget({this.warningMessage});
final String warningMessage;
@override
State<YourWidget> createState() => new _YourWidgetState();
}
class _YourWidgetState extends State<YourWidget> {
String _warningMessage;
@override
void initState() {
super.initState();
_warningMessage = widget.warningMessage;
}
@override
didUpdateWidget(ReorderableListSimple oldWidget) {
super.didUpdateWidget(oldWidget);
_warningMessage = widget.warningMessage;
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(_warningMessage),
RaisedButton(
child: Text("Change Message"),
onPressed: () {
setState(() {
_warningMessage = "new message from within the State class";
});
}
)
],
);
}
}
因此,在此示例中,您可以从外部更改warningMessage
,就像在parent
小部件中一样,您可以传递其他消息。但是,如果需要,您也可以在内部使用setState
进行设置,就像按钮的onPressed
一样。
您可能要检查的是,实际上您是否需要在Widget
中公开该属性,也许您不需要!然后,该示例将如下所示:
class YourWidget extends StatefulWidget {
@override
State<YourWidget> createState() => new _YourWidgetState();
}
class _YourWidgetState extends State<YourWidget> {
String _warningMessage;
@override
void initState() {
super.initState();
_warningMessage = "default message, no need for widget";
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(_warningMessage),
RaisedButton(
child: Text("Change Message"),
onPressed: () {
setState(() {
_warningMessage = "new message from within the State class";
});
}
)
],
);
}
}
答案 1 :(得分:0)
我通常只使用回调参数,然后将 (e) => setState((){ myField = e })
作为参数传递给我正在调用的任何外部函数。
答案 2 :(得分:-1)
只需在窗口小部件类的状态中创建一个静态值,然后在构建窗口小部件时,将其值设置为窗口小部件即可。因此,只要您想将其调用为setState()
,就只需调用静态值即可。