多个流无需处理就流向Firebase文档>>

问题描述 投票:0回答:1

我正在尝试将聊天添加到我的应用中。当我的用户开始与新用户聊天时,我在Firebase数据库中创建一个具有唯一ID的聊天室。我希望通知我的用户有关聊天室文档的任何更新(例如,新消息),因此在创建聊天室时,我还为该聊天室文档创建了新的流。不断收听具有不同流的许多文档而不处理流是否存在问题(因为我想获取用户所属的任何聊天室的最新结果。)

这是我的chatroom_screen代码:

import 'package:flutter/material.dart';
import '../models/databse_management.dart';


class ChatroomScreen extends StatefulWidget {
  static const String routeName = "/chatroom_screen";
  @override
  _ChatroomScreenState createState() => _ChatroomScreenState();
}

class _ChatroomScreenState extends State<ChatroomScreen> {
  TextEditingController _messageTextEditingController = TextEditingController();
  bool isChatroomExists;
  Stream chatroomDocStream; //my initial stream variable which is null
  @override
  Widget build(BuildContext context) {
    final Map<String, dynamic> passedArguments =
        ModalRoute.of(context).settings.arguments;
    //sedner details can be retrieved from currentUserDetails
    final String senderId = passedArguments["senderId"];
    final List<String> receiversIds = passedArguments["receiverIds"];
    final String senderUsername = passedArguments["senderUsername"];
    final List<String> receiverUsernames = passedArguments["receiverUsernames"];
    final String chatroomId = passedArguments["chatroomId"];
    if(chatroomDocStream == null){
      chatroomDocStream = Firestore.instance.collection("chatrooms").document(chatroomId).snapshots(); //if no stream was created before (first time we build the widget), we connect a stream to this chatroom documentspecified with chatroomId
    }
    isChatroomExists = isChatroomExists == null

        ? passedArguments["isChatroomExists"]
        : isChatroomExists;

    final Image senderProfilePictureUrl =
        passedArguments["senderProfilePicture"];
    final List<Image> receiverProfilePictures =
        passedArguments["receiverProfilePictures"];
    final mediaQuery = MediaQuery.of(context).size;
    final ThemeData theme = Theme.of(context);

    //we get the values from the passed argument map
    if (isChatroomExists) {
      //load the previous chats
    }
    return Scaffold(
      appBar: AppBar(
        title: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            CircleAvatar(
              backgroundImage: receiverProfilePictures[0]
                  .image, //right now only for 1 receiver but change it for multi members later
            ),
            Container(
              child: Text(receiverUsernames[0]),
              margin: const EdgeInsets.only(left: 10),
            ),
          ],
        ),
      ),
      body: //to do=> create a stream that is listening to the chatroom document for any changes
          Stack(
        children: <Widget>[
         StreamBuilder(
            //updates the chats whenever data of the chatroom document changes
            stream: chatroomDocStream,
            builder: (context, snapShot) {
              return Column(
                children: <Widget>[
                  Center(child: const Text("My chats"))
                  //message widgets go here
                ],
              );
            },
          ),
          Positioned(
            //positioned is used for positioning the widgets inside a stack. bottom: 10 means 10 pixel from bottom
            bottom: 0,
            child: Container(
              padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
              width: mediaQuery.width, //takes the total width of the screen
              decoration: BoxDecoration(
                color: theme.primaryColor.withOpacity(0.3),
              ),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Expanded(
                    //always takes the remaining space (textField widget use this as its size https://stackoverflow.com/questions/45986093/textfield-inside-of-row-causes-layout-exception-unable-to-calculate-size)
                    child: Container(
                      padding: const EdgeInsets.symmetric(
                          horizontal:
                              10), //horizontal padding for the textfield widget
                      decoration: BoxDecoration(
                        color: theme.accentColor,
                        borderRadius: BorderRadius.circular(25),
                        border: Border.all(width: 2, color: theme.primaryColor),
                      ),
                      child: TextField(
                        minLines: 1,
                        maxLines: 5,
                        controller: _messageTextEditingController,
                        decoration: const InputDecoration(
                            hintText: "Type something here...",
                            border: InputBorder
                                .none //removes all the border for textfield widget
                            ),
                      ),
                    ),
                  ),
                  Container(
                    child: Row(
                      //another row for buttons to be treated all toghether as a container in the parent row
                      children: <Widget>[
                        IconButton(
                          icon: const Icon(Icons.add),
                          onPressed: () {
                            //add media like image or pictures
                          },
                        ),
                        IconButton(
                          icon: const Icon(Icons.camera_alt),
                          onPressed: () {
                            //take picture or video
                          },
                        ),
                        IconButton(
                          icon: const Icon(Icons.send),
                          onPressed: () async {
                            if (_messageTextEditingController.text
                                .trim()
                                .isEmpty) {
                              return;
                            }
                            try {
                              await DatabaseManagement().sendMessage(
                                membersIds: [
                                  senderId,
                                  ...receiversIds
                                ], //extracts all the members of the list as seperate String items
                                //to do=>later on we have to get a list of the members as well
                                isChatroomExists: isChatroomExists,
                                chatroomId: chatroomId,
                                messageContent:
                                    _messageTextEditingController.text,
                                senderId: senderId,
                                timestamp: Timestamp
                                    .now(), //it's from firebase and records the time stamp of the sending message
                              );
                              if (isChatroomExists != true) {
                                isChatroomExists =
                                    true; //after we sent a messsage, we 100% created the chatroom so it becomes true
                              }
                            } catch (e) {
                              print(
                                e.toString(),
                              );
                              return;
                            }
                          },
                        )
                      ],
                    ),
                  )
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

这个想法是让WhatsApp这样的东西,您会在您加入的任何聊天室中收到任何更新的通知。

我正在尝试将聊天添加到我的应用中。当我的用户开始与新用户聊天时,我在Firebase数据库中创建一个具有唯一ID的聊天室。我希望我的用户收到有关...

firebase flutter google-cloud-firestore stream
1个回答
1
投票

您可以创建很多快照侦听器,但是Google建议每个客户端限制100个快照侦听器:

© www.soinside.com 2019 - 2024. All rights reserved.