首页 > 解决方案 > StreamBuilder 不断在 HotReload 上添加数据

问题描述

我是颤振和飞镖的新手,我正在尝试使用 .Net SignalRCore 和流实现一个简单的聊天应用程序。这是我的聊天屏幕的代码:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
import 'package:veo_chat/components/message_bubble.dart';
import 'package:veo_chat/constants.dart';
import 'package:veo_chat/models/message_receive_model.dart';
import 'package:veo_chat/models/message_send_model.dart';
import 'package:veo_chat/providers/chat_hub_client.dart';
import 'package:veo_chat/providers/veo_auth.dart';
import 'package:veo_chat/screens/welcome_screen.dart';

class ChatScreen extends StatefulWidget {
  static const route = '/chat';
  @override
  _ChatScreenState createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  VeoAuth auth = VeoAuth();
  bool showLoading = false;
  final chatHubClient = ChatHubClient();
  final StreamController<MessageReceiveModel> msgStreamController =
      StreamController<MessageReceiveModel>();
  final List<MessageBubble> messageWidgets = [];
  String typedMessage;
  String receiver = 'Veoxer';

  void initiateChatHub() async {
    await chatHubClient.connection.start();
    chatHubClient.connection.on('ReceiveMessage', (params) {
      print(params);
      final message = MessageReceiveModel.fromDynamic(params[0]);
      msgStreamController.sink.add(message);
    });
  }

  @override
  void initState() {
    super.initState();
    initiateChatHub();
  }

  @override
  void dispose() {
    msgStreamController.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: null,
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.close),
              onPressed: () async {
                setState(() {
                  showLoading = true;
                });
                try {
                  await auth.logout();
                } catch (e) {
                  print('An error occured during log out.');
                }
                Navigator.pushNamed(context, WelcomeScreen.route);
                setState(() {
                  showLoading = false;
                });
              }),
        ],
        title: Text('⚡️Chat'),
        backgroundColor: Colors.lightBlueAccent,
      ),
      body: ModalProgressHUD(
        inAsyncCall: showLoading,
        child: SafeArea(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              StreamBuilder<MessageReceiveModel>(
                stream: msgStreamController.stream,
                builder: (context, snapshot) {
                  if (!snapshot.hasData) {
                    return Center(
                      child: CircularProgressIndicator(),
                    );
                  }
                  if (snapshot.hasData) {
                    var messagesData = snapshot.data;
                    messageWidgets.add(
                      MessageBubble(
                        senderUsername: messagesData.senderUserName,
                        messageBody: messagesData.messageBody,
                        sendTime: DateTime.tryParse(messagesData.sendTime),
                      ),
                    );
                  }
                  return Expanded(
                    child: ListView(
                      children: messageWidgets,
                    ),
                  );
                },
              ),
              Container(
                decoration: kMessageContainerDecoration,
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Expanded(
                      child: TextField(
                        onChanged: (value) {
                          typedMessage = value;
                        },
                        decoration: kMessageTextFieldDecoration,
                      ),
                    ),
                    TextButton(
                      onPressed: () {
                        chatHubClient.sendMessage(MessageSendModel(
                            messageBody: typedMessage,
                            receiverUserName: receiver,
                            sendTime: DateTime.now()));
                      },
                      child: Text(
                        'Send',
                        style: kSendButtonTextStyle,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

一切正常,除了每次我的应用程序热加载时,我的 StreamBuilder 中的快照仍然将“hasData”属性设置为 true 并且它重新插入收到的最后一条消息并且由于某些其他原因,只有收到的第一条消息出现在屏幕上,在我与屏幕交互(例如弹出键盘)之前,所有其他内容都不会出现。我真的不明白我做错了什么。

标签: flutterdartstream-builder

解决方案


推荐阅读