firebase - 多个流到 Firebase 文档而不进行处理
问题描述
我正在尝试将聊天添加到我的应用程序中。当我的用户开始与新用户聊天时,我会在我的 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 这样的东西,您可以在您所属的任何聊天室中收到任何更新的通知。
解决方案
您可以创建大量快照侦听器,但 Google 建议每个客户端限制为 100 个快照侦听器:
资料来源:https ://cloud.google.com/firestore/docs/best-practices?hl=en#realtime_updates
推荐阅读
- java - 无法在java中加载数据库文件
- javascript - 在 Javascript 和 HTML 画布中导入关卡的外部游戏地图(保存为 `.js`)
- ios - 用于将文件下载到 iOS 的 Cordova 文件传输插件
- php - WordPress 错误与自定义简码功能一起出现
- docker - 如何通过运行传递参数以供 Dockerfile 使用?
- python - Python - 无法正确读取十六进制 0A
- c - sscanf忽略C中的空格
- jquery - 固定标题在视差图像上消失
- java - 在 Clojure 中迭代 java hashmap
- libgdx - 保持表大小但改变演员大小 libgdx