首页 > 解决方案 > Firebase Query 从两个节点一起获取数据

问题描述

我在 Firebase 实时数据库中有一个名为“Posts”的根节点。在其中,我有两个节点,分别称为“ImagePosts”和“TextPosts”。在“ImagePosts”(和“TextPosts”)中,我有各种帖子的 postId。在 postID 中,我拥有该特定帖子的所有详细信息,包括 postedAt(发布时间)。

我想要做的是编写一个查询以从“ImagePosts”和“TextPosts”中获取数据,并以降序/反向顺序显示所有帖子(也就是说,最后/最近发布的帖子应该显示在顶部根据“postedAt”在我的回收站视图中)。

请点击这里查看数据库结构

为此,我创建了一个名为 Post 的模型和两个名为“PostAdapter”和“TextPostAdapter”的适配器。我的回收站视图是“DashboardRV”。到目前为止我尝试了什么:

家庭片段代码:

public class HomeFragment extends Fragment {

ShimmerRecyclerView dashboardRV;
ArrayList<Post> postList;

public HomeFragment() {

}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_home, container, false);

    dashboardRV = view.findViewById(R.id.dashboardRv);
    dashboardRV.showShimmerAdapter();
    postList = new ArrayList<>();
    PostAdapter postAdapter = new PostAdapter(postList, getContext());
    LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
    dashboardRV.setLayoutManager(layoutManager);
    dashboardRV.addItemDecoration(new DividerItemDecoration(dashboardRV.getContext(), DividerItemDecoration.VERTICAL));
    dashboardRV.setNestedScrollingEnabled(false);

    dashboardRV.setAdapter(postAdapter);
    postList.clear();

database.getReference()
            .child("Posts")
            .child("ImagePosts")
            .addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot snapshot) {
                  
                    for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                        Post post = dataSnapshot.getValue(Post.class);
                        post.setPostId(dataSnapshot.getKey());
                        postList.add(post);
                    }
                    Collections.reverse(postList);
                    dashboardRV.hideShimmerAdapter();
                    postAdapter.notifyDataSetChanged();
                }

                @Override
                public void onCancelled(@NonNull DatabaseError error) {

                }
            });

    database.getReference()
            .child("Posts")
            .child("TextPosts")
            .addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot snapshot) {
                    postList.clear();
                    for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                        Post post = dataSnapshot.getValue(Post.class);
                        post.setPostId(dataSnapshot.getKey());
                        postList.add(post);
                    }
                    Collections.reverse(postList);
                    dashboardRV.hideShimmerAdapter();
                    textPostAdapter.notifyDataSetChanged();
                }

                @Override
                public void onCancelled(@NonNull DatabaseError error) {

                }
            });

但这种方法的问题在于它不会同时显示所有“TextPosts”和“ImagePosts”。它只显示打开应用程序上的所有图像帖子,然后当我更改片段并返回时,它会显示所有文本帖子。我只是被困在这里。

标签: javaandroidfirebasefirebase-realtime-databasegoogle-cloud-platform

解决方案


要在本地合并 2 个单独的 Firebase 实时数据库请求,我建议您使用Tasks.whenAllSuccess()方法。您可以使用以下代码行来实现这一点:

DatabaseReference imagePostsRef = database.getReference()
        .child("Posts")
        .child("ImagePosts");
DatabaseReference textPostsRef = database.getReference()
        .child("Posts")
        .child("TextPosts");

Task firstTask = imagePostsRef.get();
Task secondTask = textPostsRef.get();

Task combinedTask = Tasks.whenAllSuccess(firstTask, secondTask).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
    @Override
    public void onSuccess(List<Object> list) {
         //Do what you need to do with your list
    }
});

如您所见,当覆盖“onSuccess()”方法时,结果是一个对象列表。最后,只需将列表中的每个对象映射为 Post 类型的对象,然后将新列表传递给单个适配器。


推荐阅读