如何在类/有状态小部件之外调用 setState?

Ric*_*ick 7 state dart flutter

我有以下变量

String _warningMessage;
bool _warningVisibility;
Run Code Online (Sandbox Code Playgroud)

我想通过实现接口的类进行更新

class _UserSignupInterface extends _SignupSelectUsernamePageState
    implements UserSignupInterface {
  @override
  void onSuccess() {
    _hideWarning();
    _navigateToUserPage();
  }

  @override
  void onError(String message) {
    _isSignupClickable = true;

    if(message != null) {
      _displayWarning(message);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

使用 _displayWarning 代码(位于 内_SignupSelectUsernamePageState

void _displayWarning(String message) {
    if (message != null) {
      setState(() {
        widget._warningMessage = message;
        widget._warningVisibility = true;
      });
    }
  }
Run Code Online (Sandbox Code Playgroud)

_displayWarning(message)但是,每当我从外部调用_SignupSelectUsernamePageState. 我收到一条错误消息

Unhandled Exception: setState() called in constructor
Run Code Online (Sandbox Code Playgroud)

是否有正确的方法在类之外更新这些变量状态?_displayWarning(message)在我的例子中,我从另一个实现接口的类调用

Feu*_*Feu 3

您必须确定这是一个在小部件内部更改的值,还是一个在其外部更改的值。

如果它是内部的,常见的事情是将它们放在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";
            });
          }
        )
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,在这个示例中,您可以从外部更改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";
            });
          }
        )
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)