Flutter实现点击发送按钮添加消息到列表并在ListView显示
核心问题原因
- 状态变量定义位置错误:你将存储消息的
_messages列表、输入框控制器_messageController都定义在了build方法内部。Flutter每次触发setState都会重新执行build方法重建组件,这两个变量会被重置为空列表和全新的控制器实例,之前添加的消息就会丢失,所以界面看不到更新效果。 - 冗余结构与缺少边界判断:ListView内部嵌套了多层不必要的Column,长列表场景下性能较差;发送消息时没有做空文本校验,可能会提交空消息;没有主动释放输入框控制器,存在内存泄漏风险。
修复方案
- 将
_messages、_messageController从build方法中移出,作为当前State类的成员变量存储,保证状态不会因为组件重建丢失。 - 重写
dispose生命周期方法,释放输入框控制器避免内存泄漏。 - 可选优化:改用
ListView.builder构建消息列表,性能更优;添加reverse: true属性让新消息从底部弹出,符合聊天软件使用习惯;发送前校验文本非空。
修复后核心代码示例
class ChatPage extends StatefulWidget { const ChatPage({super.key}); @override State<ChatPage> createState() => _ChatPageState(); } class _ChatPageState extends State<ChatPage> { // 状态变量移到build外部作为类成员 final List<MessageBubble> _messages = []; final TextEditingController _messageController = TextEditingController(); @override void dispose() { // 释放控制器 _messageController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final _query = MediaQuery.of(context).size; return Scaffold( body: Column( children: [ Expanded( // 改用ListView.builder,性能更好适配长列表 child: ListView.builder( reverse: true, // 新消息从底部出现 padding: EdgeInsets.all(_query.height * 0.03), itemCount: _messages.length, itemBuilder: (context, index) { // reverse开启后需要倒序取消息 return _messages[_messages.length - 1 - index]; }, ), ), Row( children: [ Padding( padding: EdgeInsets.only(left: _query.width * 0.04), child: Container( width: _query.width * 0.8, height: 75, child: TextField( controller: _messageController, keyboardType: TextInputType.text, cursorColor: const Color.fromRGBO(168, 168, 168, 1), cursorHeight: 20.0, style: const TextStyle(fontSize: 16), decoration: const InputDecoration( labelText: 'Enter your message', labelStyle: TextStyle( color: Color.fromRGBO(166, 166, 166, 1)), border: UnderlineInputBorder( borderSide: BorderSide( color: Color.fromRGBO(166, 166, 166, 1))), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Color.fromRGBO(166, 166, 166, 1))), focusedBorder: UnderlineInputBorder( borderSide: BorderSide( color: Color.fromRGBO(166, 166, 166, 1))), hoverColor: Colors.grey), ), ), ), Padding( padding: EdgeInsets.only( top: _query.height * 0.015, ), child: InkWell( customBorder: const CircleBorder(), onTap: () { // 空文本判断,避免发送空消息 final inputText = _messageController.text.trim(); if (inputText.isEmpty) return; setState(() { _messages.add(MessageBubble( message: inputText, sender: 'Mubashir', )); _messageController.clear(); }); }, child: Padding( padding: EdgeInsets.all(_query.width * 0.04), child: Icon( Icons.send, size: _query.width * 0.07, color: AppColors().liteColorWithOpacity(1.0), ), ), ), ) ], ), ], ) ); } }
你原有的MessageBubble类代码没有问题,不需要修改。
内容的提问来源于stack exchange,提问作者Mubashir Saeed
相关产品推荐
相关产品推荐

