我有一个小部件,它显示了一个用户列表。单击列表元素时,会创建一个新的MaterialPageRoute并将其推送到导航器,以打开显示消息历史记录的该用户的聊天屏幕。
class Users extends StatefulWidget {
final User user;
Users({this.user});
@override
UsersState createState() => new UsersState();
}
class UsersState extends State<Users> {
Map<String, Conversation> _conversations = new Map<String, Conversation>();
void _sendMessage(String message, String username) {
setState(() {
_conversations[username].messages.add(
new Message(text: message, isFromUser: true)
);
});
}
void _openChat(String username) {
Navigator.of(context).push(
new MaterialPageRoute(
builder: (context) {
return new Chat(
user: widget.user,
conversation: _conversations[username],
sendMessage: _sendMessage,
);
}
)
);
}
@override
Widget build(BuildContext context) {
return new Column(
children: _onlineUsers.map((username) {
return new ListTile(
leading: new CircleAvatar(
child: new Text(username[0].toUpperCase())
),
title: new Text(username),
onTap: () => _openChat(username),
);
}).toList()
);
}
}
在聊天小部件中,按下发送按钮时,将调用UsersState._sendMessage
,通过更新当前对话来更改状态。然后运行UsersState类的构建方法,但Chat小部件不会使用添加的消息进行更新(我猜,因为没有再次调用onTap函数)。
我试图将页面路由创建作为构建方法的直接功能,但这也不起作用。在创建状态的类中设置状态后,如何自动更新新屏幕的状态?
答案 0 :(得分:1)
你想做的事情与你所拥有的有点不同;据我所知,你所拥有的是一个包含对话的小部件,然后在每次任何对话发生变化时创建新的路由。
我建议使用数据库来存储消息;在某些时候你无论如何都需要这样做。如果您只是存储在设备上,sqflite是一个很好的解决方案,而如果您希望使用FireStore将其保存到服务器可能是最简单的。
您可以拥有列出用户的主窗口小部件,但每个聊天窗口小部件本身应该是一个有状态窗口小部件,每次添加新邮件时状态都会更改。注册更改的方式取决于您使用的插件。
如果确实想在内存中只为半健壮的应用程序执行此操作,我建议您查看StreamBuilder并使用流将每封邮件发送到单个聊天或编写您自己的简单发布/订阅系统(即在创建窗口小部件时注册侦听,在窗口小部件处理时注销)。你必须传递管理注册的对象 - 我建议不要使用navigator的推送,使用pushNamed并管理Navigator / MaterialApp / WidgetApp中的东西。
虽然只是一个简单的示例(正如您在评论中所说的那样),但您可以使用InheritedWidget向下传播更改。您只需要确保InheritedWidget位于两个页面的小部件树中;如果您手动使用Navigator,则必须确保Navigator是InheritedWidget的子项,而如果您使用的是MaterialApp或WidgetsApp,则可以使用builder
参数指定一个函数在MaterialApp / WidgetsApp下面但在导航器上方构建inheritedwidget。
stock app example并不是你正在做的事情,但它是一个带有列表页面和各个页面的应用程序的示例。
答案 1 :(得分:0)
有类似的情况。我的解决方案(适合您的情况):
聊天应该扩展StatefulWidget
让聊天调用setState()并将消息添加到聊天中的消息,而不是将回调传递给聊天。
由于您只是将对话的引用传递给了聊天,因此应该还会在用户中更新您的对话地图。
当导航器弹出路线时,将重建父用户,从而反映更新的对话。
如果聊天状态与父状态无关,我想你会更新聊天状态,然后调用sendMessage回调来更新父状态?这样可以避免依赖父状态变异,有些人可能会说这是一种反模式。
到目前为止有大约2小时的颤振经验,所以我期待听到其他人是否会插话。编辑:添加第4页 - 感谢@rmtmckenzie的鸣响。