多个流到 Firebase 文档而不进行处理
Posted
技术标签:
【中文标题】多个流到 Firebase 文档而不进行处理【英文标题】:Multiple streams to firebase documents without disposing 【发布时间】:2020-06-03 01:19:42 【问题描述】:我正在尝试将聊天功能添加到我的应用程序中。 当我的用户开始与新用户聊天时,我会在我的 Firebase 数据库中创建一个具有唯一 ID 的聊天室。我希望我的用户收到有关聊天室文档的任何更新(例如:新消息)的通知,因此当我创建聊天室时,我还会为该聊天室文档创建一个新流。在不处理流的情况下不断收听具有不同流的许多文档是否存在问题(因为我想获得用户所属的任何聊天室的最新结果。)
这是我的聊天室屏幕代码:
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://***.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 的东西,您可以在您所属的任何聊天室中收到任何更新的通知。
【问题讨论】:
【参考方案1】:您可以创建大量快照侦听器,但 Google 建议每个客户端限制为 100 个快照侦听器:
来源:https://cloud.google.com/firestore/docs/best-practices?hl=en#realtime_updates
【讨论】:
从不处理这些流有问题吗?我可以让它们一直打开吗? StreamBuilder 小部件在绘制时侦听 Stream,并在处理后自动关闭 Stream。如果不是同时绘制很多StreamBuilders是没有问题的以上是关于多个流到 Firebase 文档而不进行处理的主要内容,如果未能解决你的问题,请参考以下文章
Swift 2.3 pod 更新后使用未解析的标识符 Firebase 'FIR'
未处理的异常:NoSuchMethodError:在 null 上调用了方法“toRawHandle”