【问题标题】:Flutter call setState() to update UI in another classFlutter 调用 setState() 来更新另一个类中的 UI
【发布时间】:2019-12-27 12:12:01
【问题描述】:

我试图在按下按钮时调用 setState,以便 ui 可以显示新列表,但即使使用函数我也无法使用 setState,否则它会给我一个错误,说我在构造函数中调用 setState。

这是我的 statlessWidget 代码:

class _MessageCard extends StatelessWidget {
final Mensagem message;
final int messageLenght;
final List<Mensagem> messageList;
var i;
_MessageCard(
  {@required this.message,
  @required this.messageLenght,
  @required this.messageList});

@override
Widget build(BuildContext context) {
return Center(
    child: Container(
  width: 600,
  child: InkWell(
    child: Container(
      width: 900,
      color: Colors.grey[200],
      child: Padding(
        padding: const EdgeInsets.fromLTRB(12, 0, 12, 0),
        child: Center(
          child: Container(
            width: 600,
            child: Column(
              children: <Widget>[
                ListTile(
                  leading: CircleAvatar(
                    child: Icon(
                      Icons.notifications,
                      color: Colors.red[400],
                    ),
                    backgroundColor: Colors.grey[200],
                  ),
                  title: Text(
                    (this.message.vDescricao ?? '').trim(),
                    style: TextStyle(
                      fontSize: 14,
                      color: Colors.black,
                    ),
                  ),
                  subtitle: Text(
                    (this.message.vData ?? '').trim() +
                        '   ' +
                        (this.message.vHora ?? '').trim(),
                    style: TextStyle(
                      color: Colors.red[400],
                      fontSize: 13,
                    ),
                  ),
                  trailing: FlatButton(
                      child: Text(
                        Translations.of(context)
                            .trans('finishmessageshort'),
                      ),
                      onPressed: () => _showDeleteAlertMessage(
                          this.message.vNumero, context)),
                ),
                Divider(
                  color: Colors.black54,
                ),
              ],
            ),
          ),
        ),
      ),
    ),
  ),
 ));
}

Future _showDeleteAlertMessage(String id, BuildContext context) {
return showDialog(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        title: new Text(
          Translations.of(context).trans('finishmessage') + '?',
        ),
        actions: <Widget>[
          FlatButton(
              child: new Text(
                Translations.of(context).trans('closealert'),
              ),
              onPressed: () {
                Navigator.of(context).pop();
              }),
          FlatButton(
            child: new Text(("Ok")),
            onPressed: () =>
                {_deleteMessage(id), Navigator.of(context).pop()},
          )
        ],
      );
    });
}

_deleteMessage(String id) async {
for (i = 0; i < this.messageLenght; i++) {
  if (this.messageList[0].vNumero == this.message.vNumero) {
    this.messageList.removeAt(i);
    _HomePageState().mensagemRepo.confirmMessage(this.message.vNumero);
    await _HomePageState()._getMessages();
    return this.messageList;
   }
  }
 }
}

这是我的 _getMessages()

_getMessages() async {
setState(() {
  _loading = true;
  _errorMsg = '';
});

try {
  _messages = await mensagemRepo.getMessages();

  print('loaded messages: ${_messages?.length}');
} catch (e) {
  _errorMsg = e.toString();
}

setState(() {
  _loading = false;
});

}

我怎样才能使用这个 setState?

感谢您的时间和关注

编辑:现在更新列表但不更新 UI,因为我无法从 MessageCard 设置主页状态

【问题讨论】:

  • setState 只能在有状态的小部件中使用。如果要在类之间进行通信,请使用 void 回调函数并将指针函数传递给依赖的小部件。否则使用通知和更改通知广播流。

标签: android flutter setstate statelesswidget


【解决方案1】:

您只能在StatefulWidget 中使用setState

class MessageCard extends StatefulWidget {

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

class _MessageCardState extends State<MessageCard> {
  @override
  Widget build(BuildContext context) {
    // your build method here
  }
}

【讨论】:

  • 如果我这样使用它,我无法在我的主页中调用 messageCard 构建,还是需要调用 messagecardState?
  • 在你的构建方法中调用MessageCard(),就可以了。 createState 方法将为您调用 _MessageCardState
【解决方案2】:

嗯,你不能为不存在的东西设定价值。无状态的名称本身就清楚地表明它不能拥有任何状态。将小部件更改为有状态小部件会起作用。

【讨论】:

    【解决方案3】:

    无状态小部件在渲染后无法更改状态。要使用 setState 并重新渲染小部件,使用 StatefulWidget。

    只需将您的 MessageCard 从 Stateless Widget 更改为 StatefulWidget

    class MessageCard extends StatefulWidget {
        final Mensagem message;
        final int messageLenght;
        final List<Mensagem> messageList;
        var i;
    
        MessageCard(
          {@required this.message,
            @required this.messageLenght,
            @required this.messageList});
    
          @override
          _MessageCardState createState() => _MessageCardState();
        }
    
        class _MessageCardState extends State<MessageCard> {
          @override
          Widget build(BuildContext context) {
            // your build method here
          }
        }
    

    另外,现在在 _MessageCardState 中“使用您的 MessageCard 属性”,例如 messagemessageLenghtmessageList您必须分别使用 widget.messagewidget.messageListwidget.messageLenght 等属性。

    【讨论】:

    • 如果我想访问我的其他主页小部件怎么办?我可以在我的消息卡中调用 setState 吗?
    • 使用 StatefulWidget 时,MessageCard 将无法显示。您不需要在 MessageCard 类中创建和执行任何函数、变量。无论您必须执行什么,都将在您的 State 类中完成,即 _MessageCardState 。顾名思义,状态类用于管理和更改您的小部件状态,您只能在 _MessageCardState 中使用它。
    • 所以我无法更新 MessageCard 类中另一个类的状态?
    • _MessageCardState 是管理 MessageCard 状态的类。所以,最终你改变的任何状态都会被用来改变 MasterClass 的状态。不要对有两个类 MessageCard 和 _MessageCardState 感到困惑。它们最终是相互关联的。
    • 我可以从列表中清除它们,但我似乎无法更新主类 HomePage 类中的 ui
    【解决方案4】:

    这可以刷新用户界面吗?

    _getMessages() async {
        _HomePageState()._messages = await mensagemRepo.getMessages();
    
        print('loaded messages: ${_messages?.length}');
    
        setState(() {
          _HomePageState()._messagesList();
        });
      }
    

    _messagesList() 的代码是:

    SliverChildBuilderDelegate _messagesList() {
        int count() {
          if (_errorMsg != '')
            return 1;
          else
            return _messages == null ? 0 : _messages.length;
        }
    
        return SliverChildBuilderDelegate(
          (BuildContext context, int index) {
            print("i: $index");
            if (_errorMsg != '') {
              return Padding(
                padding: EdgeInsets.all(20),
                child: ErrorMessage(
                  error: _errorMsg,
                ),
              );
            } else {
              return _MessageCard(
                  message: this._messages[index],
                  messageLength: this._messages.length,
                  messageList: this._messages);
            }
          },
          childCount: count(),
        );
      }
    

    【讨论】:

      【解决方案5】:

      我设法使它工作,通过将两个类合二为一并调用一个函数来绘制消息卡,谢谢大家的帮助和关注

      【讨论】:

        猜你喜欢
        • 2021-10-07
        • 2019-07-14
        • 2019-01-18
        • 1970-01-01
        • 1970-01-01
        • 2020-12-17
        • 2021-12-18
        • 1970-01-01
        • 2019-12-21
        相关资源
        最近更新 更多