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.