Как именно я могу гарантировать, что значение поля обновляется в конкретном документе? - PullRequest
3 голосов
/ 10 января 2020

Мой sendMessage() метод устанавливает isseen как false, и EventListener должен обновить значение false до true, если сообщение увидено другим человеком. Однако в настоящее время этого не происходит.

По-моему, я могу ошибаться, пытаясь сослаться на документ в EventListener. Я оставил последний документ пустым, потому что каждое сообщение хранится в случайно сгенерированном документе. Или же ошибка в методе onStart().

Пожалуйста, дайте мне знать, как именно я должен ссылаться на базу данных, чтобы EventListener мог правильно ссылаться на правильный документ.

EventListener

EventListener<DocumentSnapshot> eventListener = new EventListener<DocumentSnapshot>() {
        @Override
        public void onEvent(@Nullable DocumentSnapshot snapshot, @Nullable FirebaseFirestoreException e) {
            if (snapshot != null){
                String recipientId = getIntent().getStringExtra("recipientId");
                Chat chat = snapshot.toObject(Chat.class);
                if (chat != null) {
                    if (chat.getReceiver().equals(userId) && chat.getSender().equals(recipientId)){
                        HashMap<String, Object> hashMap = new HashMap<>();
                        hashMap.put("isseen", true);
                        FirebaseFirestore.getInstance().collection("chats").document(roomId).collection("messages").document().update(hashMap);
                    }
                }
                else {
                    // this is a comment.
                }
            }
        }
    };

Метод sendMessage ()

private void sendMessage(String sender,String receiver,String message){
        DocumentReference documentReference = rootRef.collection("chats").document(roomId).collection("messages").document();
        Map<String,Object> user = new HashMap<>();
        user.put("sender",sender);
        user.put("receiver",receiver);
        user.put("message",message);
        user.put("time", FieldValue.serverTimestamp());
        user.put("rid",roomId);
        user.put("isseen",false);
        documentReference.set(user,SetOptions.merge()).addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Log.d(TAG, "onSuccess: MessageSent "+ userId);
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.d(TAG, "onSuccess: Error"+ userId);
            }
        });
    }

Метод onStart ()

@Override
    protected void onStart() {
        super.onStart();
        listenerRegistration = FirebaseFirestore.getInstance().collection("chats").document(roomId).collection("messages").document().addSnapshotListener(eventListener);
    }

1 Ответ

0 голосов
/ 10 января 2020

Проблема заключается в том, как настроить слушателя:

listenerRegistration = FirebaseFirestore.getInstance()
        .collection("chats").document(roomId)
        .collection("messages").document()
        .addSnapshotListener(eventListener);

При вызове document() в третьей строке создается новый пустой документ. И вы присоединяете слушателя к этому документу, который никто никогда не собирается писать.

Вызов document() в sendMessage() - это хорошо и даже требуется, так как вы пишете новый документ там. Но при подключении слушателя к новому, неиспользованному документу он никогда не будет вызываться.

Та же проблема возникает, когда вы пытаетесь обновить документ с помощью:

FirebaseFirestore.getInstance().collection("chats").document(roomId).collection("messages").document().update(hashMap);

Вызов document() здесь также создается новый пустой документ. А поскольку документ еще не существует, вызов update() завершается неудачно, поскольку вы не можете обновить несуществующий документ.

Обычно вы захотите прослушать все документы в коллекции, с чем-то вроде этого:

FirebaseFirestore.getInstance()
    .collection("chats").document(roomId)
    .collection("messages")
    .addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(@Nullable QuerySnapshot results,
                            @Nullable FirebaseFirestoreException e) {
            if (e != null) {
                Log.w(TAG, "Listen failed.", e);
                return;
            }

            String recipientId = getIntent().getStringExtra("recipientId");
            for (QueryDocumentSnapshot doc : results) {
                Chat chat = snapshot.toObject(Chat.class);
                if (chat != null) {
                    if (chat.getReceiver().equals(userId) && chat.getSender().equals(recipientId)){
                        HashMap<String, Object> hashMap = new HashMap<>();
                        hashMap.put("isseen", true);
                        doc.getReference().update(hashMap);
                    }
                }
            }
        }
    });

Это слушатель другого типа, потому что теперь вы можете вызывать несколько документов. Но, кроме того, что зацикливаясь на документах, код внутри этого l oop обычно такой же, как и при прослушивании одного документа.

И вы можете видеть, что я обновляю соответствующие документы, вызывая getReference() на них.


Приведенный выше код считывает все документы в приложение Android, а затем обновляет только те документы, для которых указан отправитель / получатель. эффективнее использовать запрос , который выполнит фильтрацию на сервере и вернет только соответствующие документы в приложение Android.

Это будет выглядеть примерно так:

String recipientId = getIntent().getStringExtra("recipientId");
FirebaseFirestore.getInstance()
    .collection("chats").document(roomId)
    .collection("messages")
    .whereEqualTo("receiver", recipientId)
    .whereEqualTo("sender", userId)
    .addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(@Nullable QuerySnapshot results,
                            @Nullable FirebaseFirestoreException e) {
            if (e != null) {
                Log.w(TAG, "Listen failed.", e);
                return;
            }

            for (QueryDocumentSnapshot doc : results) {
                Chat chat = snapshot.toObject(Chat.class);
                if (chat != null) {
                    HashMap<String, Object> hashMap = new HashMap<>();
                    hashMap.put("isseen", true);
                    doc.getReference().update(hashMap);
                }
            }
        }
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...