Flutter - 小部件的状态没有改变
Posted
技术标签:
【中文标题】Flutter - 小部件的状态没有改变【英文标题】:Flutter - State of widget is not changing 【发布时间】:2020-05-27 22:47:03 【问题描述】:我几乎是Flutter
的新手,正在尝试开发一个聊天应用程序。每当用户发送消息时,它应该更改Widget
的State
,并且消息应该显示在Listview
中。
情况是Widget State
在Button
按下时不会改变。但是,如果我 Hot Reload
我的应用程序会更改 State
的 Widget
并显示消息。我为视图使用了两个Widgets
,并在Child Widget
中调用了setState()
方法。如何从Child Widget
刷新Widget
的State
。
请查看我的代码并告诉我解决方案。提前致谢。
父小部件:
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,)),
),
],
),
);
【问题讨论】:
你可以阅读这个。 flutter.dev/docs/development/data-and-backend/state-mgmt/simple @Darish 我的情况和你建议的文件不一样。 您需要的解决方案是某种状态管理设置,在该文档中,它清楚地解释了如何设置。setState
仅适用于此特定 Widget 的状态。您不能 setState
并将更改应用到 MyClass
。
@kuhnroyal 我正在尝试设置ChatScreen
的状态。
【参考方案1】:
首先,@Darish 是正确的,您可能应该使用另一种状态管理系统,但对于“如何从子小部件刷新小部件的状态”这个问题。我将提供两个简单的答案:
将您的_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);
...
直接从您的ChatWidgetState
访问您的ChatState
:
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 更接近于其他可以说更好的状态管理方法,但两者都是直接从子小部件更新父小部件状态的示例。
【讨论】:
感谢您的解释和帮助。我还没有尝试过你的解决方案。我会尝试它,如果它有效,我会投票给它作为正确的解决方案。再次非常感谢。以上是关于Flutter - 小部件的状态没有改变的主要内容,如果未能解决你的问题,请参考以下文章