I am making a chat activity using Firebase to store messages and a RecyclerView
to display them. Per the below adapter costructor, when the RecyclerView
is initialized, the last 50 messages are queried from Cloud Firestore and arranged in descending order by a Unix timestamp. I then use setStackFromEnd(true) in my chat activity to flip the order they are displayed in, as the newest messages should be near the bottom, and new messages are added to the adapter's message list using messageList.add(0,message)
This presents a problem. In onBindViewHolder, the previously acceptable:
Message message = messageList.get(position);
holder.message.setText(message.getMessage());
holder.author.setText(message.getAuthor() + ":");
No longer works because the message being entered into the RecyclerView will be a repeat of the most recent message when the RecyclerView is loaded(the one in position 0). i.e.:
- message one
- message one
- message one
- message one
Instead of:
- message one
- message two
- message three
- message four
Where "message one" is the most recent message when the RecyclerView
is created. Replacing this with:
Message message = messageList.get(0);
holder.message.setText(message.getMessage());
holder.author.setText(message.getAuthor() + ":");
In onBindViewHolder
to get the true most recent message will have it appear on the screen, but also subsequently replace all items with the most recent message when they are recycled. Ultimately I'd like to have queried messages listed bottom to top in order of recency, while continuing to place the newest messages toward the bottom(like every chat app ever), without having to query an entire collection. Where should I correct my mistake and how?
Adapter Constructor:
public ChatRecyclerViewAdapter(Context mContext, ArrayList<String> mMessage, ArrayList<String> mAuthor, String mRoomID, FirebaseFirestore firestore) {
messageList = new ArrayList<>();
firestore = FirebaseFirestore.getInstance();
mCollection = firestore.collection(mRoomID + "_messages");
Query query = mCollection.orderBy("timestamp", Query.Direction.DESCENDING).limit(50);
query.addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots, @Nullable FirebaseFirestoreException e) {
for (DocumentChange documentChange : queryDocumentSnapshots.getDocumentChanges()) {
switch (documentChange.getType()) {
case ADDED:
documentChange.getDocument();
Message message = documentChange.getDocument().toObject(Message.class);
messageList.add(0,message);
notifyItemInserted(messageList.size());
}
}
}
});
Attempt at querying next oldset set of messages on scroll:
query.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
if (queryDocumentSnapshots.size() > 0) {
//Get the last visible document
DocumentSnapshot lastVisible = queryDocumentSnapshots.getDocuments().get(messageList.size()-1);
//Construct a new query starting at this document and get the next batch of messages
Query next = mCollection.orderBy("timestamp", Query.Direction.DESCENDING).startAfter(lastVisible).limit(20);
next.get();
}
}
});