You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现点击发送按钮添加消息到列表并在ListView显示

核心问题原因
  • 状态变量定义位置错误:你将存储消息的_messages列表、输入框控制器_messageController都定义在了build方法内部。Flutter每次触发setState都会重新执行build方法重建组件,这两个变量会被重置为空列表和全新的控制器实例,之前添加的消息就会丢失,所以界面看不到更新效果。
  • 冗余结构与缺少边界判断:ListView内部嵌套了多层不必要的Column,长列表场景下性能较差;发送消息时没有做空文本校验,可能会提交空消息;没有主动释放输入框控制器,存在内存泄漏风险。
修复方案
  1. 将_messages、_messageController从build方法中移出,作为当前State类的成员变量存储,保证状态不会因为组件重建丢失。
  2. 重写dispose生命周期方法,释放输入框控制器避免内存泄漏。
  3. 可选优化:改用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 14:45:05