从Firestore数据库更新时ArrayList的顺序更改

时间:2018-11-27 15:53:02

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

问题:我的列表项显示顺序错误。当我关闭片段并重新打开它时,会发生这种情况。然后,它首先显示所有“已发送的消息”,然后显示所有接收到的消息。但是,当我编写消息时,它们以正确的顺序显示。只有当我关闭片段/活动并重新打开它时,顺序才发生变化。

我在getMessages方法中调用on-create方法以打开包含视图的片段。

我尝试过的事情:

  • 使用Firestore orderby方法(同时使用String和TimeStamp)
  • 使用更简单的Firestore Snapshot Listener

问题:

  • 如何最好地将Firestore Snapshot Listener与RecyclerView一起使用,并正确维护项目顺序?

这是我主要的“ getMessages”方法:

public void getLiveChatMessages(final ArrayList<ChatConversationMessage> messageArrayList, final ChatConversationAdapter adapter, final String matchClicked) {

    final String userID = onboardingFirebaseUser.returnCurrentUserId();

    final CollectionReference messagesCollectionRef = db.collection("users")
            .document(userID)
            .collection("matches")
            .document(matchClicked)
            .collection("messages");

    messagesCollectionRef
            .orderBy("TimeStamp", Query.Direction.DESCENDING)
            .addSnapshotListener(new EventListener<QuerySnapshot>() {
                                     @Override
                                     public void onEvent(@Nullable QuerySnapshot value,
                                                         @Nullable FirebaseFirestoreException e) {
                                         if (e != null) {
                                             Log.w(TAG, "listen:error", e);
                                             return;
                                         }


                                         for (QueryDocumentSnapshot doc : value) {
                                             if (doc.get("Message") != null) {

                                                 if (doc.get("Message") != null && doc.get("From user with ID").equals(userID)) {
                                                     String message = doc.getString("Message");

                                                     messageArrayList.add(new ChatConversationMessage(message));
                                                     adapter.notifyDataSetChanged(); //Ensures messages are visible immediately

                                                 } else if (doc.get("Message") != null) {
                                                     final String message = doc.getString("Message");

                                                     DocumentReference matchRef = db.collection("users")
                                                             .document(userID)
                                                             .collection("matches")
                                                             .document(matchClicked);

                                                     matchRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                                                         @Override
                                                         public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                                                             if (task.isSuccessful()) {
                                                                 DocumentSnapshot document = task.getResult();
                                                                 if (document.exists()) {
                                                                     imageReference = storageReference.child(document.getString("profileImg"));
                                                                     messageArrayList.add(new ChatConversationMessage(message, imageReference));
                                                                     adapter.notifyDataSetChanged(); //Ensures messages are visible immediately

                                                                 } else {
                                                                     Log.d(TAG, "No such document");
                                                                 }
                                                             } else {
                                                                 Log.d(TAG, "get failed with ", task.getException());
                                                             }
                                                         }
                                                     });

                                                 }
                                             }
                                         }
                                     }
                                 });}}

1 个答案:

答案 0 :(得分:0)

一段时间后,我发现了问题。

我正在快照侦听器中的新引用上调用get方法。当您这样做时,它会影响ArrayList中项目的顺序。

要解决此问题,请确保Firestore中创建ArrayList所需的所有项目都存储在与每个文档中的字段相同的位置(而不是两个不同的位置)。这样,您无需在快照侦听器中的新引用上使用单独的get方法。这也可以使客户端代码更干净。对于未来的Google员工,以下是我重组方法的方法:

messagesCollectionRef
            .orderBy("TimeStamp", Query.Direction.ASCENDING)
            .addSnapshotListener(new EventListener<QuerySnapshot>() {
                @Override
                public void onEvent(@Nullable QuerySnapshot snapshots,
                                    @Nullable FirebaseFirestoreException e) {
                    if (e != null) {
                        Log.w(TAG, "listen:error", e);
                        return;
                    }

                    for (DocumentChange dc : snapshots.getDocumentChanges()) {

                        switch (dc.getType()) {
                            case ADDED:
                                Log.d(TAG, "New message added" + dc.getDocument().getData());

                                if (dc.getDocument().get("Message") != null && dc.getDocument().get("From user with ID").equals(userID)) {
                                    String message = dc.getDocument().getString("Message");
                                    messageArrayList.add(new ChatConversationMessage(CURRENTUSER, message, null));
                                    adapter.notifyDataSetChanged();
                                }

                                if (dc.getDocument().get("Message") != null && dc.getDocument().get("From user with ID").equals(matchClicked)) {
                                    String message = dc.getDocument().getString("Message");
                                    imageReference = storageReference.child(dc.getDocument().getString("profileImg"));
                                    messageArrayList.add(new ChatConversationMessage(OTHERUSER, message, imageReference));
                                    adapter.notifyDataSetChanged();
                                }
                                break;
                            case MODIFIED:
                                break;
                            case REMOVED:
                                break;
                        }
                    }
                }
            });

如您所见,我现在将imageReference字符串存储在Firestore中的每个消息文档中,并且可以用与检索添加到ArrayList所需的所有其他数据相同的方式来检索它。您需要做的主要代码更改是将数据写入云的位置(即写入/设置Firestore文档)。那是您需要确保所有内容都作为字段值添加到文档中的地方,因此您无需将其放在单独的位置。祝你好运!