android - 从 LiveData 触发第二个查询并合并结果(Firestore)?

标签 android firebase google-cloud-firestore android-architecture-components android-livedata

我有两个集合:Users 和 Books。无论 Users OR Books 是否更新,我都需要获取它们的结果,然后将结果合并到一个 LinkedHashMap 中以用作 listView 菜单。

我认为 MediatorLiveData 是可行的方法,但如果我将 Users 查询和 Books Query 放入其中,那么我会从两个 LiveData 对象之一中得到 null,因为只有一个或另一个触发。我想也许如果其中一个触发,那么我可能会在 MediatorLiveData 中的每个 addSource() 中运行一个查询,但我不确定这是否是可行的方法。

我关于 MediatorLiveData 的帖子在这里: Using MediatorLiveData to merge to LiveData (Firestore) QuerySnapshot streams is producing weird results

我的两个查询和LiveData对象如下:

//getUsers query using FirebaseQueryLiveData class
private Query getUsersQuery() {
    FirebaseAuth mAuth = FirebaseAuth.getInstance();

    adminID = mAuth.getUid();
    query = FirebaseFirestore.getInstance().collection("admins")
            .document(adminID)
            .collection("users")
    return query;
}

private FirebaseQueryLiveData usersLiveData = new FirebaseQueryLiveData(getUsersQuery());


//getBooks query using FirebaseQueryLiveData class
private Query getBooksQuery () {
    FirebaseGroupID firebaseGroupID = new FirebaseGroupID(getApplication());
    groupID = firebaseGroupID.getGroupID();
    query = FirebaseFirestore.getInstance().collection("books")
            .whereEqualTo("groupID", groupID)      
    return query;
}

private FirebaseQueryLiveData booksLiveData = new FirebaseQueryLiveData(getBooksQuery()); 

不知何故,当 Users 更新时,我也需要获取 Books 的数据然后合并它们,但如果 Books 更新我也需要这样做,然后获取 Users 的数据并合并它们。

任何想法将不胜感激。

附加说明/观察 好的,所以我没有完全排除 MediatorLiveData 对象。当然,它允许我在同一个方法中监听两个不同的 LiveData 对象,但是,我不想直接合并这两个对象,因为我需要单独对每个 liveData 对象进行操作。举个例子:usersLiveData 触发是因为我们创建或修改了一个用户,然后我需要查询书籍,获取结果并合并用户和书籍等。

下面是我目前的 MediatorLiveData:

//MediatorLiveData merge two LiveData QuerySnapshot streams
private MediatorLiveData<QuerySnapshot> usersBooksLiveDataMerger() {
    final MediatorLiveData<QuerySnapshot> mediatorLiveData = new MediatorLiveData<>();
    mediatorLiveData.addSource(usersLiveData, new Observer<QuerySnapshot>() {
        @Override
        public void onChanged(@Nullable QuerySnapshot querySnapshot) {
            mediatorLiveData.setValue(querySnapshot);
        }
    });
    mediatorLiveData.addSource(booksLiveData, new Observer<QuerySnapshot>() {
        @Override
        public void onChanged(@Nullable QuerySnapshot querySnapshot) {
            mediatorLiveData.setValue(querySnapshot);
        }
    });
    return mediatorLiveData;
}

现在它正在返回其他 LiveData 源的空结果。相反,我需要查询然后合并。关于如何做到这一点的任何想法?关于这件事的内容并不多。

我尝试将查询放在使用 Transformations.map() 调用的函数中,但由于它是异步调用,因此在查询完成之前调用返回语句。

这是我对函数的尝试:

    private class ListenUsersGetBooks implements Function<QuerySnapshot, LinkedHashMap<User, List<Book>>> {

        @Override
        public LinkedHashMap<User, List<Book>> apply(final QuerySnapshot input) {
            userBookList = new LinkedHashMap<>();
            getBooksQuery().get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    List<User> users = input.toObjects(User.class);
                    List<Book> books = task.getResult().toObjects(Book.class);
                    Log.d(TAG, "USERLIST! " + users);
                    Log.d(TAG, "BOOKLIST! " + books);
                    for (User user : users) {
                        bookList = new ArrayList<>();
                        for (Book book : books) {
                            if (user.getUserID().equals(book.getUserID())
                                    && book.getBookAssigned()) {
                                bookList.add(book);
                            }
                            else if (user.getAllBookID().equals(book.getBookID())) {
                                bookList.add(book);
                            }
                        }
                        userBookList.put(user, bookList);
                    }
                    Log.d(TAG,"OBSERVE userBookList: " + userBookList);
                }
            });
            return userBookList;
        }
    } 

最佳答案

这是您可以执行的操作的简单版本,我希望它有意义。

您接近 MediatorLiveData .而不是 MediatorLiveData<QuerySnapshot>您可能想使用这样的自定义对象:

class MyResult {

  public QuerySnapshot usersSnapshot;
  public QuerySnapshot booksSnapshot;

  public MyResult() {}

  boolean isComplete() {
    return (usersSnapshot != null && booksSnapshot != null);
  }
}

然后在你的观察者中,做这样的事情:

private MediatorLiveData<MyResult> usersBooksLiveDataMerger() {
    final MediatorLiveData<MyResult> mediatorLiveData = new MediatorLiveData<>();
    mediatorLiveData.addSource(usersLiveData, new Observer<QuerySnapshot>() {
        @Override
        public void onChanged(@Nullable QuerySnapshot querySnapshot) {
            MyResult current = mediatorLiveData.getValue();
            current.usersSnapshot = querySnapshot;
            mediatorLiveData.setValue(current);
        }
    });
    mediatorLiveData.addSource(booksLiveData, new Observer<QuerySnapshot>() {
        @Override
        public void onChanged(@Nullable QuerySnapshot querySnapshot) {
            MyResult current = mediatorLiveData.getValue();
            current.booksSnapshot = querySnapshot;
            mediatorLiveData.setValue(current);
        }
    });
    return mediatorLiveData;
}

然后当您观察合并的实时数据时:

usersBooksLiveDataMerger().observe(new Observer<MyResult>() {

    @Override
    public void onChanged(@Nullable MyResult result) {
        if (result == null || !result.isComplete()) {
          // Ignore, this means only one of the queries has fininshed
          return;
        }

        // If you get to here, you know all the queries are ready!
        // ...
    }

});

关于android - 从 LiveData 触发第二个查询并合并结果(Firestore)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50500766/

相关文章:

android - 动态更改 Activity 背景

android - 如何打开默认文件管理器

android - 使用离线 map 进行应用程序开发

html - 如何确定电子邮件是否已使用 Firebase 简单登录注册?

firebase - 如何从ion select中获取item的所有信息?

java - 加载一个大的正数 BigInteger

javascript - 基于属性值的 Firebase Firestore 安全规则

javascript - 如何从 firebase 中的函数检索数据

reactjs - 如何在 React.js 中将图像上传到 Firebase 存储并同时将 URL 上传到 Firestore?

swift - Firestore - 如果文档不存在,GetDocument() 会使应用程序崩溃