繁体   English   中英

Firebase 查询从两个节点一起获取数据

[英]Firebase Query to fetch data from two nodes together

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

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

请点击此处查看数据库结构

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

Home Fragment 代码:

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”。 它只显示打开应用程序上的所有图像帖子,然后当我更改片段并返回时,它会显示所有文本帖子。 我只是被困在这里。

一次只为一个回收者视图使用一个适配器:

这是具有(图像和文本帖子)的单个适配器的代码:

postList = new ArrayList<>();

PostAdapter postAdapter = new PostAdapter(postList, getContext());
dashboardRV.setAdapter(postAdapter);

// call clear before refreshing the list
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.sort(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) {

                    for (DataSnapshot dataSnapshot : snapshot.getChildren())              
                        Post post = dataSnapshot.getValue(Post.class);
                        post.setPostId(dataSnapshot.getKey());
                        postList.add(post);
                    }
                    Collections.sort(postList);
                    dashboardRV.hideShimmerAdapter();
                    postAdapter.notifyDataSetChanged();
                }

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

                }
            });

// 使 Post 类实现与获取后对列表进行排序相当:

// A class 'Post' that implements Comparable
class Post implements Comparable<Post>
{
    ...
 
    // Used to sort posts by their postedAt
    public int compareTo(Post p)
    {
        return this.postedAt - p.postedAt;
    }
 
    ...
}

此链接将有助于探索如何根据postedAt 进行排序:Using Comparable

要在本地合并 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 类型的对象,并将新列表传递给单个适配器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM