Android StreamBuilder为每个更新生成两次快照
我正在尝试构建一个聊天应用程序,它可以在显示消息的同时显示时间。以下是主要代码:Android StreamBuilder为每个更新生成两次快照,android,firebase,flutter,dart,google-cloud-firestore,Android,Firebase,Flutter,Dart,Google Cloud Firestore,我正在尝试构建一个聊天应用程序,它可以在显示消息的同时显示时间。以下是主要代码: import 'package:flutter/material.dart'; import 'package:flash_chat/constants.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; final _fireStore =
import 'package:flutter/material.dart';
import 'package:flash_chat/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
final _fireStore = Firestore.instance;
FirebaseUser loggedInUser;
class ChatScreen extends StatefulWidget {
static String chatScreen = 'ChatScreenpage1';
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final messageTextEditingController = TextEditingController();
String messageText;
final _auth = FirebaseAuth.instance;
@override
void initState() {
super.initState();
getUserDetail();
}
void getUserDetail() async {
try {
final createdUser = await _auth.currentUser();
if (createdUser != null) {
loggedInUser = createdUser;
}
} catch (e) {
print(e);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
_auth.signOut();
Navigator.pop(context);
}),
],
title: Text('⚡️Chat'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
StreambuilderClass(),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextEditingController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
messageTextEditingController.clear();
_fireStore.collection('messages').add({
'sender': loggedInUser.email,
'text': messageText,
'time': FieldValue.serverTimestamp()
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class StreambuilderClass extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _fireStore
.collection('messages')
.orderBy('time', descending: false)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.blueAccent,
),
);
}
final messages = snapshot.data.documents.reversed;
List<MessageBubble> messageBubbles = [];
for (var message in messages) {
final messageText = message.data['text'];
final messageSender = message.data['sender'];
final messageTime = message.data['time'] as Timestamp;
final currentUser = loggedInUser.email;
print('check time: $messageTime'); //print(message.data['time']); both gives null
print('check sender: $messageSender');
print('check sender: $messageText');
print(snapshot.connectionState);
final messageBubble = MessageBubble(
sender: messageSender,
text: messageText,
isMe: currentUser == messageSender,
time: messageTime,
);
messageBubbles.add(messageBubble);
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
children: messageBubbles),
);
});
}
}
class MessageBubble extends StatelessWidget {
final String text;
final String sender;
final bool isMe;
final Timestamp time;
MessageBubble({this.text, this.sender, this.isMe, this.time});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment:
isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(
' $sender ${DateTime.fromMillisecondsSinceEpoch(time.seconds * 1000)}',
style: TextStyle(color: Colors.black54, fontSize: 12),
),
Material(
color: isMe ? Colors.blueAccent : Colors.white,
borderRadius: isMe
? BorderRadius.only(
topLeft: Radius.circular(30),
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30))
: BorderRadius.only(
topRight: Radius.circular(30),
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30)),
elevation: 6,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
child: Text(
text,
style: TextStyle(
fontSize: 20, color: isMe ? Colors.white : Colors.black),
),
),
),
],
),
);
}
}
导入“包装:颤振/材料.省道”;
导入“package:flash_chat/constants.dart”;
导入“包:firebase_auth/firebase_auth.dart”;
导入“包:cloud_firestore/cloud_firestore.dart”;
final _fireStore=fireStore.instance;
FirebaseUser日志用户;
类ChatScreen扩展StatefulWidget{
静态字符串chatScreen='ChatScreenpage1';
@凌驾
_ChatScreenState createState()=>\u ChatScreenState();
}
类_ChatScreenState扩展状态{
最终消息TextEditingController=TextEditingController();
字符串消息文本;
final _auth=FirebaseAuth.instance;
@凌驾
void initState(){
super.initState();
getUserDetail();
}
void getUserDetail()异步{
试一试{
final createdUser=wait_auth.currentUser();
if(createdUser!=null){
loggedInUser=createdUser;
}
}捕获(e){
印刷品(e);
}
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
前导:空,
行动:[
图标按钮(
图标:图标(Icons.close),
已按下:(){
_auth.signOut();
Navigator.pop(上下文);
}),
],
标题:文本('⚡️聊天室),,
背景颜色:Colors.lightBlueAccent,
),
正文:安全区(
子:列(
mainAxisAlignment:mainAxisAlignment.spaceBetween,
crossAxisAlignment:crossAxisAlignment.stretch,
儿童:[
StreambuilderClass(),
容器(
装饰:kMessageContainerDecoration,
孩子:排(
crossAxisAlignment:crossAxisAlignment.center,
儿童:[
扩大(
孩子:TextField(
控制器:messageTextEditingController,
一旦更改:(值){
messageText=值;
},
装饰:KMessageExtField装饰,
),
),
扁平按钮(
已按下:(){
messageTextEditingController.clear();
_fireStore.collection('messages')。添加({
“发件人”:loggedInUser.email,
“文本”:messageText,
“时间”:FieldValue.serverTimestamp()
});
},
子:文本(
“发送”,
样式:ksendButtonExtStyle,
),
),
],
),
),
],
),
),
);
}
}
类StreambuilderClass扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回流生成器(
流:_fireStore
.collection('消息')
.orderBy('time',降序:false)
.snapshots(),
生成器:(上下文,快照){
如果(!snapshot.hasData){
返回中心(
子对象:循环压缩机指示器(
背景颜色:Colors.blueAccent,
),
);
}
最终消息=snapshot.data.documents.reversed;
列表messageBubbles=[];
for(消息中的var消息){
final messageText=message.data['text'];
final messageSender=message.data['sender'];
final messageTime=message.data['time']作为时间戳;
最终currentUser=loggedInUser.email;
print('check time:$messageTime');//print(message.data['time']);两者都给出null
打印('check sender:$messageSender');
打印('check sender:$messageText');
打印(快照.连接状态);
final messageBubble=messageBubble(
发件人:messageSender,
text:messageText,
isMe:currentUser==messageSender,
时间:messageTime,,
);
messageBubbles.add(messageBubble);
}
扩大回报(
子:ListView(
相反:是的,
填充:边缘组。对称(水平:10,垂直:20),
孩子们:泡泡),,
);
});
}
}
类MessageBubble扩展了无状态小部件{
最终字符串文本;
最终字符串发送器;
最终目标;
最终时间戳时间;
MessageBubble({this.text,this.sender,this.isMe,this.time});
@凌驾
小部件构建(构建上下文){
返回填充(
填充:所有边缘设置(10.0),
子:列(
横轴对齐:
isMe?CrossAxisAlignment.end:CrossAxisAlignment.start,
儿童:[
正文(
“$sender${DateTime.fromMillisSecondsSinceepoch(time.seconds*1000)}”,
样式:TextStyle(颜色:Colors.black54,字体大小:12),
),
材料(
颜色:isMe?颜色。蓝色口音:颜色。白色,
边界半径:isMe
?仅限边界半径(
左上:半径。圆形(30),
左下角:半径。圆形(30),
右下角:半径。圆形(30))
:仅限边界半径(
右上角:半径。圆形(30),
左下角:半径。圆形(30),
右下角:半径。圆形(30)),
标高:6,
孩子:填充(
填充:边缘组。对称(水平:20,垂直:15),
子:文本(
文本,
样式:TextStyle(
字体大小:20,颜色:isMe?颜色。白色:颜色。黑色),
),
),
),
],
),