'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