我正在使用Android Room和Firestore以MVVM模式制作聊天室功能。我将Room用作UI的“单一事实来源”,并使用存储库将数据上载到Firestore,以及从firestore下载新数据并将其插入Room。
问题是,每次从网上下载新消息时,我的存储库都会尝试多次将其插入数据库中。我第一次进入聊天室活动(在其中获得与消息存储库关联的视图模型),一切正常。
但是,当我继续进行另一项活动并返回到聊天室时,如果我不断切换活动并返回,则所有消息都会成倍出现,然后变成三重奏,四重奏等。
使用SQLite的REPLACE策略,我设法避免在会议室数据库中插入重复的消息,但是快照侦听器和存储库的逻辑的潜在问题仍然存在,这导致大量额外的计算和错误。 / p>
我试图跟踪问题的根源,但没有成功。我不知道我是偶然创建了View-model类,Repository类还是存储库中的SnapshotListener的多个副本。
ViewModel:
public class MessageViewModel extends AndroidViewModel {
private MessageRepository mRepository;
private LiveData<List<Message>> mNewMessages;
public MessageViewModel (Application application) {
super(application);
mRepository = new MessageRepository(application);
}
public LiveData<List<Message>> getNewMessages(String room_id, int extra_messages) {
mNewMessages = mRepository.getNewMessages(room_id, extra_messages);
return mNewMessages;
}
public void insert(Message message) { mRepository.insert(message); }
public void resetUnreadMessages(String room_id){
mRepository.resetUnreadMessages(room_id);
}
}
存储库:
private List<String> my_rooms;
//....
MessageRepository(Application application) {
MessageRoomDatabase db = MessageRoomDatabase.getDatabase(application);
mMessageDao = db.messageDao();
firedb = FirebaseFirestore.getInstance();
initMyRooms();
}
private void initMyRooms()
{
firedb.collection("users").document(my_id).addSnapshotListener(new EventListener<DocumentSnapshot>() {
@Override
public void onEvent(@Nullable DocumentSnapshot documentSnapshot,
@Nullable FirebaseFirestoreException e) {
//....etc
my_rooms = userData.getRoom_ids();
addFireStoreListener();
}
//.....
});
}
private void increaseRoomUnreadMessages(String room_id){
MessageRoomDatabase.databaseWriteExecutor.execute(() -> {
mMessageDao.increaseRoomUnreadMessages(room_id);
});
}
private void addFireStoreListener(){
for(String room_id : my_rooms) {
colRef = firedb.collection("rooms").document(room_id).collection("messages");
listenerRegistration = colRef.whereGreaterThan("date", sync_date)
.addSnapshotListener(myListener);
}
}
EventListener<QuerySnapshot> myListener = new EventListener<QuerySnapshot>() {
@Override
public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException e) {
for (DocumentChange dc : value.getDocumentChanges()) {
Message message = dc.getDocument().toObject(Message.class);
switch (dc.getType()) {
case ADDED:
// This is the part that gets called multiple times when I switch activities and relaunch the chatroom activity
writeIntoRoom(message);
increaseRoomUnreadMessages(message.getRoom_id());
break;
}
}
}
};
活动:
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// .......
mMessageViewModel = new ViewModelProvider(this).get(MessageViewModel.class);
}
我非常想知道这些代码中是否有某些内容表明我在做错误的事情。为了简洁起见,我删除了部分代码。如果您需要文件中的完整代码,请告诉我。