skip to Main Content

I want to sort data in Firebase realtime database.

enter image description here

I am using timestamp as key when saving data and I want to sort data by timestamps. I used below code for this purpose.

  Widget buildList(ChatUser chatUser) {
return Flexible(
    child: StreamBuilder(
        stream: _service
            .getMessages(chatUser.uid!)
            .orderByKey()
            .onValue,
        builder: (context, snapshot) {
          List<ChatMessage> messageList = [];
          if (snapshot.hasData) {
            final myMessages = Map<dynamic, dynamic>.from(
                (snapshot.data as DatabaseEvent).snapshot.value
                    as Map<dynamic, dynamic>);

            myMessages.forEach((key, value) {
              final currentMessage = Map<String, dynamic>.from(value);
              final message = ChatMessage().fromJson(currentMessage);
              messageList.add(message);
            });

            if (messageList.isNotEmpty) {
              return ListView.builder(
                  padding: const EdgeInsets.all(10),
                  reverse: true,
                  itemCount: messageList.length,
                  controller: scrollController,
                  itemBuilder: (context, index) {
                    return buildItem(index, messageList[index], chatUser);
                  });
            } else {
              return const Center(
                child: Text('Henüz Mesaj yok.'),
              );
            }
          } else {
            return const Center(
              child: CircularProgressIndicator(
                color: Colors.red,
              ),
            );
          }
        }));

}

As a result, data does not come according to key values, it comes in different orders.

result

Any suggestions ? Thanks.

2

Answers


  1. The problem is in how you process the results here:

      if (snapshot.hasData) {
        final myMessages = Map<dynamic, dynamic>.from(
            (snapshot.data as DatabaseEvent).snapshot.value
                as Map<dynamic, dynamic>);
    
        myMessages.forEach((key, value) {
          final currentMessage = Map<String, dynamic>.from(value);
          final message = ChatMessage().fromJson(currentMessage);
          messageList.add(message);
        });
    

    The order of the keys inside a Map is by definition undefined. So when you call (snapshot.data as DatabaseEvent).snapshot.value as Map<dynamic, dynamic>), you’re actually dropping all ordering information that the database returns.

    To process the results in the correct order, iterate over the children of the snapshot, and only then convert each child to a Map.

    Login or Signup to reply.
  2. Complementing Frank, try to assign snapshot to a List of snapshots using List snapshotList = xxx.children.toList(); If you do something like snapshotList[i].value you will notice that the key is not present, the solution to get it back is to use the get .key.

    You can see bellow an exemple how I did to solve the same problem in my project.

    final List<DataSnapshot> snapshotList = snapshot.data.children.toList();
    
    final List<Map> commentsList = [];
    
    for (var i in snapshotList) {
      Map<String?, Map> comment = {i.key: i.value as Map};
      commentsList.add(comment);
    }
    

    In the code above, commentsList will get you a list of Maps ordered according to original database.

    I hope this help. If anyone has a more straightforward solution, please, share with us.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search