Проблема заключается в том, как настроить слушателя:
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);
}
}
}
});