[SOLVED] How to sort an ArrayList in onComplete method, firebase

Issue

This Content is from Stack Overflow. Question asked by Marcel Sanchez

I’m developing and application messages and I want to get the ArrayList sorted of that messages inside onComplete method:

first I go to the collection “messages” to return all the fields of that collection and then I order it by timestamp, and it works fine, it return the query sort it by timestamp

ArrayList getMessages = new ArrayList<>();

I got users collection that I need to use for get the properties of that user who is sending the message, but I need to use it inside the for loop

firebaseFirestore.collection(threads).orderBy(timestamp).addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException error) {
        
        
                for(QueryDocumentSnapshot document : value){
                
                    firebaseFirestore.collection("users").document(document.getString("senderId")).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                        @Override
                        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                            getMessages.add(document.getString("message");

                            getTimestamp.add(date);
                            getUserInfo.add(user.getString("firstName"));
                          
                            if (completeCount++ == value.size()-1) {
                                recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
                                adapter = new AdapterRecyclerViewThreads(getActivity(), titleThreads, ThreadsId,
                                        getUserInfo, getUserImage, getTimestamp, getAnswer);
                                recyclerView.setAdapter(adapter);
                                

                            }

                        }
                    });


                }
            }
        });

outside onComplete method in foor loop the array returns (I want to get this):
message 1
message 2
message 3
message 4 ….

inside onComplete method in for loop array returns:

message 4
message 3
message 1
message 2

as I said the orderBy works fine, but the problem is when I get the datas inside onComplete method

I know that this is normal to happen because firebase takes time to process the query, but I need to use the collections “users” inside the for loop for return the data of the userr…



Solution

I don’t think there’s a way to guarantee the order in which the load operations complete on Firestore. The easiest way I can think of to keep them in sync is by adding the message to the array in the outer loop, and then updating it in-place with the user info in the inner loop.

So, create a class to hold the MessageAndUserInfo and then:

ArrayList<MessageAndUserInfo> messageAndUserInfos = new ArrayList<>();
...
firebaseFirestore.collection(threads).orderBy(timestamp).addSnapshotListener(new EventListener<QuerySnapshot>() {
    @Override
    public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException error) {
        for(QueryDocumentSnapshot document : value){        
            MessageAndUserInfo msg = new MessageAndUserInfo(document.getString("message"));
            messageAndUserInfos.add(msg);
            firebaseFirestore.collection("users").document(document.getString("senderId")).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                @Override
                public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                    msg.setUserInfo(user.getString("firstName"));
                    ...


This Question was asked in StackOverflow by Marcel Sanchez and Answered by Frank van Puffelen It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?