在显示Firebase查询的RecyclerView的开头插入对象

时间:2018-10-04 23:21:08

标签: java android firebase android-recyclerview google-cloud-firestore

我正在使用Firebase进行聊天活动来存储消息,并使用RecyclerView来显示消息。根据下面的适配器构造函数,在初始化RecyclerView时,将从Cloud Firestore中查询最后50条消息,并按Unix时间戳按降序排列。然后,我在聊天活动中使用setStackFromEnd(true)来翻转它们的显示顺序,因为最新消息应该在底部附近,并且使用messageList.add(0,message)<将新消息添加到适配器的消息列表中。 / p>

这带来了一个问题。在onBindViewHolder中,以前可以接受的:

Message message = messageList.get(position);

holder.message.setText(message.getMessage());
holder.author.setText(message.getAuthor() + ":");

不再起作用,因为在加载RecyclerView时(位置0中的那个),输入到RecyclerView中的消息将是最新消息的重复。即:

  • 留言一
  • 留言一
  • 留言一
  • 留言一

代替:

  • 留言一
  • 消息二
  • 消息三
  • 消息四

创建RecyclerView时,“消息一”是最新消息。替换为:

Message message = messageList.get(0);

holder.message.setText(message.getMessage());
holder.author.setText(message.getAuthor() + ":");

onBindViewHolder中获取真实的最新消息将使它出现在屏幕上,但随后在回收这些项目时,也将所有项目替换为最新消息。最终,我希望按最近顺序从下至上查询消息,同时继续将最新消息置于最下面(就像以前的每个聊天应用程序一样),而不必查询整个集合。我应该在哪里纠正错误以及如何纠正?

适配器构造器:

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());
                    }
                }
            }
        });

尝试滚动查询下一组旧消息:

 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();
                }
            }
        });

1 个答案:

答案 0 :(得分:1)

代码中的问题是,您使用Unix timestamp而不是Date对象以降序排序。为使其正常工作,建议您将时间戳存储为日期的方式进行更改。为此,请参见我在 post 中的回答,在此我解释了如何使用POJO classMap来实现这一目标。

在这里您可以找到有关如何创建 Chat App 的教程,在此我已经完全解释了您要寻找的东西。请查看以下屏幕截图:

enter image description here

在我的代码中,以下行用作查询:

val query = rootRef!!
    .collection("messages")
    .document(roomId)
    .collection("roomMessages")
    .orderBy("sentAt", Query.Direction.ASCENDING)