【问题标题】:Order of ArrayList changes when updating from Firestore Database从 Firestore 数据库更新时 ArrayList 的顺序发生变化
【发布时间】:2019-04-29 09:56:08
【问题描述】:

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

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

我的尝试:

  • 使用 Firestore orderby 方法(使用字符串和时间戳)
  • 使用更简单的 Firestore 快照侦听器

问题:

  • 如何最好地将 Firestore 快照侦听器与 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());
                                                             }
                                                         }
                                                     });

                                                 }
                                             }
                                         }
                                     }
                                 });}}

【问题讨论】:

  • 请添加您的数据库结构。
  • @AlexMamo 数据库结构已添加
  • 请将其添加为截图。
  • @AlexMamo 添加 :-)
  • 你说哪个查询不维护顺序?

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


【解决方案1】:

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

我在快照侦听器中对新引用调用 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 文档)。这就是您需要确保将所有内容作为字段值添加到您的文档的地方,因此您不需要在不同的位置获取它。祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-13
    • 2022-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多