微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Flutter - 输入 TextField 被 TextEditingController 清除,但输入的消息似乎“仍然存在”非空

如何解决Flutter - 输入 TextField 被 TextEditingController 清除,但输入的消息似乎“仍然存在”非空

我有一个聊天应用程序,它使用由 TextEditingController 控制的单个 TextField 来输入文本消息。 按关联的图标按钮发送消息如果消息不为空,然后清除 TextEditingController。这一切都完美无缺。发送消息后,文本输入字段被清除。

但是,错误来了,如果我再次按下发送按钮,消息会再次发送。这是怎么回事,我该如何预防?

class NewMessage extends StatefulWidget {
  @override
  _NewMessageState createState() => _NewMessageState();
}

class _NewMessageState extends State<NewMessage> {
  final _controller = TextEditingController();
  var _enteredMessage = '';

  void _sendMessage() async {
    FocusScope.of(context).unfocus();
    final user = FirebaseAuth.instance.currentUser;
    final userData = await FirebaseFirestore.instance
        .collection('users')
        .doc(user.uid)
        .get();
    FirebaseFirestore.instance.collection('chat').add({
      'text': _enteredMessage,'createdAt': Timestamp.Now(),'userId': user.uid,'username': userData.data()['username'],'userImage': userData.data()['image_url']
    });
    _controller.clear();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: 8),padding: EdgeInsets.all(8),child: Row(
        children: <Widget>[
          Expanded(
            child: TextField(
              controller: _controller,textCapitalization: TextCapitalization.sentences,autocorrect: true,enableSuggestions: true,decoration: Inputdecoration(labelText: 'Send a message...'),onChanged: (value) {
                setState(() {
                  _enteredMessage = value;
                });
              },),IconButton(
            color: Theme.of(context).primaryColor,icon: Icon(
              Icons.send,onpressed: _enteredMessage.trim().isEmpty ? null : _sendMessage,)
        ],);
  }
}

    

解决方法

您正在清除按钮回调中的控制器 _controller.clear(),但您真正发送到 Firebase 的不是 _controller 文本而是变量 _enteredMessage 没有被清除。

如果你只是发送控制器文本而不是 _enteredMessage 问题应该可以解决:

    FirebaseFirestore.instance.collection('chat').add({
      'text': _controller.text,'createdAt': Timestamp.now(),'userId': user.uid,'username': userData.data()['username'],'userImage': userData.data()['image_url']
    });

同时始终在 Stateful Widget onDispose 方法中处理您的控制器以避免内存泄漏。

编辑: 调用按钮回调的条件也应更改为:

...
onPressed: _controller.text.isEmpty ? null : _sendMessage
...
,

我发现这里最简单的解决方案是更换

 onPressed: _enteredMessage.trim().isEmpty ? null : _sendMessage,

 onPressed: () {
            if (_controller.text.trim().isNotEmpty) _sendMessage();
          }
         
,

将 TextEditingController AND 用于 TextField 的 onChanged 事件可能会出现问题。该问题在此处进行了深入讨论:TextEditingController vs OnChanged

就我而言,我最终决定采用 TextEditingController 解决方案。这样,我们就可以去掉 _enteredMessage 变量和 onChanged/setState() 语句。

相反,我们需要向 TextEditingController 添加一个侦听器,并在 setState() 方法中调用 initState()

最后,我们需要处理 _controller 方法中的 dispose() 以防止内存泄漏。

这是我的TextEditingController 唯一解决方案的代码:

class NewMessage extends StatefulWidget {
  @override
  _NewMessageState createState() => _NewMessageState();
}

class _NewMessageState extends State<NewMessage> {
  var _controller = TextEditingController();

  @override
  void initState() {
    _controller = TextEditingController();
    _controller.addListener(() {
      setState(() {});
    });
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _sendMessage() async {
    FocusScope.of(context).unfocus();
    final user = FirebaseAuth.instance.currentUser;
    final userData = await FirebaseFirestore.instance
        .collection('users')
        .doc(user.uid)
        .get();
    FirebaseFirestore.instance.collection('chat').add({
      'text': _controller.text,'userImage': userData.data()['image_url']
    });
    _controller.clear();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: 8),padding: EdgeInsets.all(8),child: Row(
        children: <Widget>[
          Expanded(
            child: TextField(
              controller: _controller,textCapitalization: TextCapitalization.sentences,autocorrect: true,enableSuggestions: true,decoration: InputDecoration(labelText: 'Send a message...'),),IconButton(
            color: Theme.of(context).primaryColor,icon: Icon(
              Icons.send,onPressed: _controller.text.trim().isEmpty ? null : _sendMessage,],);
  }
}

    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。