'Does the onValue listener for Realtime Database return items in the same order that they are added to the database?
I don't see this specified in the docs anywhere. Does this listener return the node's data in the order that it is added to the node? For example, if I add message1, then message2, then message3, does this listener return data in that same order of message1, message2, message3?
The application uses a widget called ChatScreen to show the ReceivedChats widget (chat body) and the MsgInput widget (chat footer). There is no chat header (unless you count the app bar?).
ChatScreen widget:
class ChatScreen extends StatelessWidget {
ChatScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final groupIDPath = 'groupChats/0exUS3P2XKFQ007TIMmm';
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.menu),
color: Colors.white,
onPressed: () {},
),
title: Text(
'Group Name',
),
actions: [
IconButton(
icon: Icon(Icons.search),
color: Colors.white,
onPressed: () {},
)
],
backgroundColor: Color.fromRGBO(51, 50, 49, 1.0),
elevation: 0.0,
),
body: Column(
children: [
Expanded(
flex: 11,
child: Row(
children: [
Expanded(
child: ReceivedChats(groupIDPath: groupIDPath),
),
],
),
),
],
)
);
}
}
ReceivedChats widget
class ReceivedChats extends StatefulWidget {
const ReceivedChats({Key? key, required this.groupIDPath}) : super(key: key);
final groupIDPath;
@override
_ReceivedChatsState createState() => _ReceivedChatsState();
}
class _ReceivedChatsState extends State<ReceivedChats> {
late StreamSubscription _receivedChatsStream;
final _database = FirebaseDatabase.instance.ref();
@override
void initState() {
super.initState();
_activateListeners();
}
void _activateListeners() {
_receivedChatsStream = _database.child(groupIDPath).onValue.listen((event) {
final data = event.snapshot.value;
print('data: ' + data.toString()); //The data printed here is out of order
});
}
@override
Widget build(BuildContext context) {
//...widget build stuff...//
}
}
Insert into RTDB:
class MessageDao {
String groupIDPath;
DatabaseReference _messagesRef;
FirebaseStorage _firebaseStorage;
String _currentUID;
MessageDao({required this.groupIDPath}):
_messagesRef = FirebaseDatabase.instance.ref().child(groupIDPath),
_firebaseStorage = FirebaseStorage.instance,
_currentUID = FirebaseAuth.instance.currentUser!.uid.toString();
//Save a single text message to RTDB
void saveMessage(ChatData message) async {
_messagesRef.push().set(message.toJson());
}
The data currently in RTDB:
{
"groupChats": {
"0exUS3P2XKFQ007TIMmm": {
"-N1HB8ik8RekJGQ-R9X-": {
"filterID": "",
"URL": "",
"text": "1",
"timestamp": "2022-05-04 22:08:20.782466",
"type": "1",
"uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
},
"-N1HB9LQ-NAEzp3rNr4V": {
"filterID": "",
"URL": "",
"text": "2",
"timestamp": "2022-05-04 22:08:23.323476",
"type": "1",
"uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
},
"-N1HDx2BAMNjio0o6gSU": {
"filterID": "",
"URL": "",
"text": "3",
"timestamp": "2022-05-04 22:20:35.275138",
"type": "1",
"uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
},
"-N1HDxeB9V5mvb4i4w9o": {
"filterID": "",
"URL": "",
"text": "4",
"timestamp": "2022-05-04 22:20:37.772181",
"type": "1",
"uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
},
"-N1HDy3jGshk_sLK4_oG": {
"filterID": "",
"URL": "",
"text": "5",
"timestamp": "2022-05-04 22:20:39.471453",
"type": "1",
"uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
},
"-N1HEYpMpz4L6TMDLlgr": {
"filterID": "",
"URL": "",
"text": "6",
"timestamp": "2022-05-04 22:23:14.133822",
"type": "1",
"uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
},
"-N1HE_be1sn86ZNu8KI5": {
"filterID": "",
"URL": "",
"text": "7",
"timestamp": "2022-05-04 22:23:21.450031",
"type": "1",
"uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
},
"-N1HEaW0HDvCjqexapy4": {
"filterID": "",
"URL": "",
"text": "8",
"timestamp": "2022-05-04 22:23:25.121275",
"type": "1",
"uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
}
}
}
}
Solution 1:[1]
The relevant code in your question is:
_database.child('groupChats/0exUS3P2XKFQ007TIMmm').onValue.listen((event) {
final data = event.snapshot.value;
print('data: ' + data.toString()); //The data printed here is out of order
})
Since you call event.snapshot.value
on the snapshot of the data at groupChats/0exUS3P2XKFQ007TIMmm
, you get a Map
of the data at that path. And the keys in a map are by definition not ordered.
If you want to process the child nodes in the order that they were return from the database, loop over event.snapshot.children
:
_database.child('groupChats/0exUS3P2XKFQ007TIMmm').onValue.listen((event) {
event.snapshot.children.forEach((snapshot) {
print('${snapshot.key}: ${snapshot.value}');
})
})
If you want to return the child nodes in a specific order from the database, call one of the orderBy...
method. For example, to order on timestamp:
_database.child('groupChats/0exUS3P2XKFQ007TIMmm').orderByChild('timestamp').onValue.listen((event) {
event.snapshot.children.forEach((snapshot) {
print('${snapshot.key}: ${snapshot.value}');
})
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Frank van Puffelen |