# #android #firebase #flutter #dart #google-cloud-firestore
Вопрос:
Я создал базовое приложение для чата с помощью firebase после завершения моего урока. но приложение не всегда отображает сообщения по порядку. Кроме того, мои сообщения должны начинаться снизу, но это не всегда так.
Я реализовал подобные пакеты firebase и firestore, так как получал сообщения об ошибках при упоминании версии.
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
animated_text_kit: ^4.1.1
firebase_core:
firebase_auth:
cloud_firestore:
modal_progress_hud: ^0.1.3
В учебнике показано, что вы должны добавить .reversed после документов, подобных приведенному ниже коду.
final messages = snapshot.data.documents.reversed;
Но когда я попытался сделать то же самое, свойство документа не существует, вместо этого мы должны использовать .docs
, и затем я попытался добавить .reversed
его после документов, но все равно проблема сохраняется, и сообщения приходят случайным образом. Я также попытался удалить коллекцию из firebase, как показано в руководстве.
ниже приведен код для извлечения потока сообщений.
class streamOfMessages extends StatelessWidget {
const streamOfMessages({@required this.users,});
final CollectionReference users;
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: users.snapshots(),
// ignore: missing_return
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
if(!snapshot.hasData){
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.blueAccent,
),
);
}
final messages = snapshot.data.docs.reversed;
List<messageBubble> messageWidgets = [];
for(var message in messages){
final messageText = message.data()['text'];
final messageSender = message.data()['sender'];
final messageWidget = messageBubble(
message: messageText,
sender: messageSender,
isMe: userEmail == messageSender,
);
messageWidgets.add(messageWidget);
}
return Expanded(
child: ListView(
children: messageWidgets,
reverse: true,
),
);
});
}
}
Я также попытался добавить метку времени, но мне кажется, что я делаю что-то не так. любая помощь очень ценится, спасибо.
Я написал код в файле ChatScreen dart, где я определил все, например, отображение сообщений и редактирование текста.
Все остальное работает нормально, просто сообщения отображаются в неправильном порядке.
ниже приведен полный код экрана чата
мы очень ценим любую помощь.
import 'package:flutter/cupertino.dart';
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 _auth = FirebaseAuth.instance;
final _firestore = FirebaseFirestore.instance;
String userEmail;
class ChatScreen extends StatefulWidget {
static String id = 'chat_screen';
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final messageController = TextEditingController();
CollectionReference users = FirebaseFirestore.instance.collection('messages');
String messageText;
@override
void initState() {
super.initState();
loggeduser();
}
void loggeduser(){
try{
final user = _auth.currentUser;
if(user != null){
print(user.email);
userEmail = user.email;
}
}catch(e){
print(e);
}
}
void getMessages() async {
await for (var snapshot in _firestore.collection('messages').snapshots()){
for (var message in snapshot.docs){
print(message.data());
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.logout),
onPressed: () {
_auth.signOut();
Navigator.pop(context);
}),
],
title: Text('⚡️Chat'),
centerTitle: true,
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
streamOfMessages(users: users),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
messageController.clear();
_firestore.collection('messages').add({
'text' : messageText,
'sender' : userEmail,
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
// ignore: camel_case_types
class streamOfMessages extends StatelessWidget {
const streamOfMessages({@required this.users,});
final CollectionReference users;
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: users.snapshots(),
// ignore: missing_return
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
if(!snapshot.hasData){
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.blueAccent,
),
);
}
final messages = snapshot.data.docs.reversed;
List<messageBubble> messageWidgets = [];
for(var message in messages){
final messageText = message.data()['text'];
final messageSender = message.data()['sender'];
final messageWidget = messageBubble(
message: messageText,
sender: messageSender,
isMe: userEmail == messageSender,
);
messageWidgets.add(messageWidget);
}
return Expanded(
child: ListView(
children: messageWidgets,
reverse: true,
),
);
});
}
}
// ignore: camel_case_types
class messageBubble extends StatelessWidget {
final String message;
final String sender;
final bool isMe;
messageBubble({this.message, 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: [
Text('$sender',
style: TextStyle(fontSize:10.0, color: Colors.black54),
),
Material(
borderRadius: isMe ? BorderRadius.only(topLeft: Radius.circular(30.0),bottomLeft: Radius.circular(30.0),bottomRight: Radius.circular(30.0)) :
BorderRadius.only(bottomLeft: Radius.circular(30.0),bottomRight: Radius.circular(30.0),topRight: Radius.circular(30.0)),
elevation: 5.0,
color: isMe ? Colors.lightBlueAccent : Colors.white,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 10.0,horizontal: 10.0),
child: Text(message,
style: TextStyle(fontSize: 16.0,
color: isMe ? Colors.white : Colors.black54),),
)
),
],
),
);
}
}
Комментарии:
1. Насколько я могу судить, ваш код нигде не указывает порядок для данных — так что это, вероятно, объясняет, почему сообщения отображаются в неопределенном порядке.
2. Хорошо, спасибо за ответ, я постараюсь уточнить какой-нибудь заказ.
3. Спасибо, что это сработало. и извините за позднюю благодарность.
Ответ №1:
Итак, я нашел ответ, который вам нужно добавить в код метку времени и метод сортировки в список, и проблема решена. Ниже приведен код, в котором вносятся изменения.
«…..» = означает тот же код, никаких изменений не требуется.
............
Expanded(
child: TextField(
controller: messageController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
messageController.clear();
_firestore.collection('messages').add({
'text' : messageText,
'sender' : userEmail,
'time' : DateTime.now(), --------------> Change here
});
print(DateTime.now());
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),..............
еще одно изменение ниже
.............
child: CircularProgressIndicator(
backgroundColor: Colors.blueAccent,
),
);
}
final messages = snapshot.data.docs.reversed;
List<messageBubble> messageWidgets = [];
for(var message in messages){
final messageText = message.data()['text'];
final messageSender = message.data()['sender'];
final messageTime = message.data()['time']; ---------> added
final messageWidget = messageBubble(
message: messageText,
sender: messageSender,
isMe: userEmail == messageSender,
time: messageTime, -----------------------------------> Add this
);
messageWidgets.add(messageWidget); -----------------------------> Add bot
messageWidgets.sort((a , b ) => b.time.compareTo(a.time)); ------> h lines
}
return Expanded(
child: ListView(
children: messageWidgets,
reverse: true,
),
);
Ниже еще одно изменение
.............
class messageBubble extends StatelessWidget {
final String message;
final String sender;
final bool isMe;
final Timestamp time; ------------------> This is added
messageBubble({this.message, this.sender, this.isMe, this.time}); ----> add this.time
@override
Widget build(BuildContext context) {