如何触发LiveData二次查询并合并Firestore双集合更新结果?
解决Firestore双集合更新时合并数据的问题
我懂你现在遇到的麻烦了:用MediatorLiveData的时候,每次只有一个数据源触发更新,另一个总是返回null,而且在Transformations.map里做异步查询根本得不到正确结果——这都是因为异步操作的特性,加上你之前的MediatorLiveData只是简单转发单个快照导致的。
核心思路应该是:先缓存两个集合的最新数据,只有当两者都持有有效数据时,再执行合并操作。下面是具体的实现方案:
第一步:重构MediatorLiveData实现
修改你的usersBooksLiveDataMerger方法,让它缓存两个数据源的快照,每次任一数据源更新时,先更新缓存,再检查是否可以执行合并:
private MediatorLiveData<LinkedHashMap<User, List<Book>>> usersBooksLiveDataMerger() { final MediatorLiveData<LinkedHashMap<User, List<Book>>> mergedLiveData = new MediatorLiveData<>(); // 缓存两个集合的最新快照 QuerySnapshot usersCache = null; QuerySnapshot booksCache = null; // 监听用户集合的更新 mergedLiveData.addSource(usersLiveData, new Observer<QuerySnapshot>() { @Override public void onChanged(@Nullable QuerySnapshot usersSnapshot) { usersCache = usersSnapshot; // 尝试合并并发送数据 attemptMerge(usersCache, booksCache, mergedLiveData); } }); // 监听书籍集合的更新 mergedLiveData.addSource(booksLiveData, new Observer<QuerySnapshot>() { @Override public void onChanged(@Nullable QuerySnapshot booksSnapshot) { booksCache = booksSnapshot; // 尝试合并并发送数据 attemptMerge(usersCache, booksCache, mergedLiveData); } }); return mergedLiveData; }
第二步:实现合并逻辑
单独抽离合并方法,确保只有当两个快照都非空时,才执行你需要的映射逻辑:
private void attemptMerge(QuerySnapshot usersSnapshot, QuerySnapshot booksSnapshot, MediatorLiveData<LinkedHashMap<User, List<Book>>> targetLiveData) { // 只有两个快照都有效时才继续 if (usersSnapshot == null || booksSnapshot == null) { return; } // 转换为实体类列表 List<User> userList = usersSnapshot.toObjects(User.class); List<Book> bookList = booksSnapshot.toObjects(Book.class); LinkedHashMap<User, List<Book>> userBookMap = new LinkedHashMap<>(); // 执行你原本的合并逻辑 for (User user : userList) { List<Book> assignedBooks = new ArrayList<>(); for (Book book : bookList) { if ((user.getUserID().equals(book.getUserID()) && book.getBookAssigned()) || user.getAllBookID().equals(book.getBookID())) { assignedBooks.add(book); } } userBookMap.put(user, assignedBooks); } // 发送合并后的结果给观察者 targetLiveData.setValue(userBookMap); }
为什么这个方案能解决你的问题?
- 缓存机制:每次任一集合更新时,我们先把最新快照缓存起来,不会丢失另一个集合的已有数据,彻底避免了null的问题。
- 实时合并:不管是Users还是Books集合更新,都会触发合并逻辑,保证ListView的数据源始终是最新的完整数据。
- 规避异步坑:我们不需要在合并时手动调用
get()做单次查询,而是依赖FirebaseQueryLiveData的实时监听,完全适配LiveData的生命周期特性。
额外小提示
如果你的FirebaseQueryLiveData在初始化时会发送一次初始数据(哪怕集合是空的),那这个方案会在两个初始数据都到达后,自动生成第一个合并结果,完美适配ListView的初始化需求。
内容的提问来源于stack exchange,提问作者Brian Begun
相关产品推荐
相关产品推荐

