Flutter-小部件的状态未更改

时间:2020-02-12 11:25:54

标签: flutter dart widget state

我对Flutter几乎是陌生的,正在尝试开发一个聊天应用程序。每当用户发送消息时,都应更改State中的Widget,并且消息应显示在Listview中。

情况是Widget State按下时Button不变。但是,如果我Hot Reload我的应用程序更改了State中的Widget,则显示消息。我在视图中使用两个Widgets,并且在setState()中调用了Child Widget方法。如何从State刷新Widget中的Child Widget

请查看我的代码,并告诉我解决方案。预先感谢。



父小部件:

class ChatScreen extends StatefulWidget {

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

class ChatState extends State<ChatScreen> {

  static const int _logout = 303;

  @override
  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(
        title: Text(Strings.appNameString),
        actions: <Widget>[

          //IconButton(icon: Icon(Icons.add), onPressed: () {}),

          PopupMenuButton<int>(

            icon: Icon(Icons.more_vert),
            elevation: 10,
            //padding: EdgeInsets.all(5),
            offset: Offset(0, 100),
            itemBuilder: (BuildContext context) => [

              PopupMenuItem(child: Text("Logout"), value: _logout,),
              //PopupMenuDivider(height: 5,),
            ],
            onSelected: (value) {

              switch(value) {

                case _logout: {

                  MyClass.SignOutofGoogle();
                } break;

                default: break;
              }
            },
          ),
        ],
      ),
      body: Column(
//        crossAxisAlignment: CrossAxisAlignment.center,
//        mainAxisSize: MainAxisSize.max,
//        mainAxisAlignment: MainAxisAlignment.end,

        children: <Widget>[

          Flexible(child: ListView.builder(
              padding: new EdgeInsets.all(8.0),
              reverse: true,
              itemBuilder: (_, int index) => MyClass.messages[index],
              itemCount: MyClass.messages.length)),
          Container(
              child: ChatWidget()),
        ],
      ),
    );
  }

}



子小部件:

class ChatWidget extends StatefulWidget {

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

class ChatWidgetState extends State<ChatWidget> {

  final TextEditingController _textController = new TextEditingController();

  Widget _buildTextComposer() {
    return Container(
      margin: const EdgeInsets.symmetric(horizontal: 10.0),

      child: Align(

        child: Column(

          children: <Widget>[
            Divider(height: 5.0, color: Colors.lightBlue,),
            Container(

              height: 6.8 * SizeConfig.heightSizeMultiplier,
              child: Row(

                children: <Widget>[
                  Container(
                    child: IconButton(
                        icon: Icon(Icons.add_photo_alternate),
                        iconSize: 6.7 * SizeConfig.imageSizeMultiplier,
                        color: Colors.lightBlueAccent,
                        onPressed: () {}),
                  ),
                  Flexible(
                    child: TextField(
                      controller: _textController,
                      onSubmitted: _handleSubmitted,
                      decoration: InputDecoration.collapsed(
                          hintText: "Send a message"),
                    ),
                  ),
                  Container(
                    margin: EdgeInsets.symmetric(horizontal: 4.0),

                    child: IconButton(
                        icon: Icon(Icons.send),
                        iconSize: 6.7 * SizeConfig.imageSizeMultiplier,
                        color: Colors.lightBlueAccent,
                        onPressed: () {
                          _handleSubmitted(_textController.text);
                        }),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _handleSubmitted(String text) {

    _textController.clear();

    ChatMessage message = new ChatMessage(
      text: text,
    );

    setState(() {
      MyClass.messages.insert(0, message);
    });
  }

  @override
  Widget build(BuildContext context) {

    return _buildTextComposer();
  }
}


class ChatMessage extends StatelessWidget {

  final String text;

  ChatMessage( {
    this.text
  });

  @override
  Widget build(BuildContext context) {
    return new Container(
      margin: const EdgeInsets.symmetric(vertical: 10.0),

      child: Row(
        //crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.end,

        children: <Widget>[
          Column(
            crossAxisAlignment: CrossAxisAlignment.end,

            children: <Widget>[
              //Text(MyClass.loggeduser.userName, style: Theme.of(context).textTheme.subhead),
              Text("Sajib", style: Theme.of(context).textTheme.subhead),
              Container(
                margin: const EdgeInsets.only(top: 5.0),
                child: Text(text),
              ),
            ],
          ),
          Container(
            margin: const EdgeInsets.only(right: 6.0, left: 12.0),

            child: CircleAvatar(
              //backgroundImage: NetworkImage(MyClass.loggeduser.photoUrl)),
                child: Icon(Icons.account_circle, color: Colors.lightBlueAccent,)),
          ),
        ],
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:1)

首先,@ Darish是正确的,因为您可能应该使用另一种状态管理系统,但要问“如何从子窗口小部件刷新窗口小部件的状态”这一问题。我将提供两个简单的答案:

  1. _handleSubmitted方法移至ChatState小部件,并将其传递给ChatWidget

    class ChatState extends State<ChatScreen> {
    
      ...
      @override
      Widget build(BuildContext context) {
          ...
          Container(
            child: ChatWidget(onMessageSubmitted: this._handleSubmitted)),
          ...
      }
    
      void _handleSubmitted(String text) {
        ChatMessage message = new ChatMessage(
          text: text,
        );
    
        setState(() {
          MyClass.messages.insert(0, message);
        });
      }
    }
    

    然后从您的孩子小部件:

    class ChatWidget extends StatefulWidget {
    
      final Function(String) onMessageSubmitted;
    
      ChatWidget({this.onMessageSubmitted});
    
      @override
      ChatWidgetState createState() => ChatWidgetState();
    }
    
    class ChatWidgetState extends State<ChatWidget> {
      ...
    
      Widget _buildTextComposer() {
        ...
        TextField(
          controller: _textController,
          onSubmitted: _handleSubmitted,
          decoration: InputDecoration.collapsed(
          hintText: "Send a message"),
        ),
        ...
        IconButton(
          ...
          onPressed: () {
            _handleSubmitted(_textController.text);
          },
        ),
        ...
      }
    
      void _handleSubmitted(String text) {
        _textController.clear();
    
        widget.onMessageSubmitted(text);
      }
      ...
    }
    
  2. 直接从您的ChatState访问您的ChatWidgetState

    class ChatScreen extends StatefulWidget {
    
      ...
    
      static ChatState of(BuildContext context) => context.findAncestorStateOfType<ChatState>();
    }
    
    class ChatState extends State<ChatScreen> {
    
      ...
    
      void onMessageSubmitted(String text) {
        ChatMessage message = new ChatMessage(
          text: text,
        );
    
        setState(() {
          MyClass.messages.insert(0, message);
        });
      }
    }
    

    然后在您的ChatWidget中可以保持原样,但在ChatWidgetState中更改_handleSubmitted的方法如下:

    void _handleSubmitted(String text) {
      _textController.clear();
    
      ChatScreen.of(context).onMessageSubmitted(text);
    }
    

数字2与状态管理的其他可以争论的方法更接近,但是这两个示例都是直接从子窗口小部件更新父窗口小部件的状态的示例。