【问题标题】:How to chain 2 EventListeners in Firebase-Android so that the first one doesn't continue until second one finishes?如何在 Firebase-Android 中链接 2 个 EventListener,以便第一个在第二个完成之前不会继续?
【发布时间】:2023-04-05 13:51:02
【问题描述】:

我正在尝试从侦听器 A 从 Firebase 获取一些数据,然后我将根据从侦听器 A 获得的一些 ID 在侦听器 B 的不同节点下搜索,当我从侦听器 B 接收数据时,我想追加它到监听器A数据。 基本上我在 Firebase 中有 2 个节点:帖子和用户。帖子有一些数据和一个用户 ID。当我想显示数据库中的所有帖子时,我将每个帖子添加到 RecyclerView,但在将它们添加到该视图之前,我需要获取一些用户数据,然后(合并这两个收集的数据)将其添加到 recyclerView .

我在网上找不到任何可以尝试的东西(除了一些 UI 阻塞的东西,我宁愿远离,因为我是 Android 新手)。我知道 Firebase 是异步的,Java 没有 Promises 或 async/await,所以 IDK 还有什么可以尝试的。在我目前的实现中,我没有达到我想要的(显然)。

private void initialPopulatePostsFromDB(){
        mDatabase.limitToFirst(2).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                List<IndividualPost> postsDB = new ArrayList<>();

                for(DataSnapshot postSnapShot : dataSnapshot.getChildren()){

 oldestPostId = postSnapShot.getKey();
                    final IndividualPost indivPost = postSnapShot.getValue(IndividualPost.class);
                    indivPost.setContents(typePostContents);

                    /*
                    FirebaseDatabase.getInstance().getReference("/users").child(indivPost.getUserId()).addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                            userAccount = dataSnapshot.getValue(UserAccount.class);

                            indivPost.setUserId(userAccount.getName());
                            System.out.println("[1] ACC NAME: " + indivPost.getUserId());
                        }
                        @Override
                        public void onCancelled(@NonNull DatabaseError databaseError) {

                        }
                    });
                    */

                    FirebaseDatabase.getInstance().getReference("/users").child(indivPost.getUserId()).addListenerForSingleValueEvent(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                            userAccount = dataSnapshot.getValue(UserAccount.class);

                            indivPost.setUserId(userAccount.getName());
                            System.out.println("[1] ACC NAME: " + indivPost.getUserId());
                        }
                        @Override
                        public void onCancelled(@NonNull DatabaseError databaseError) {

                        }
                    });

                    System.out.println("[2] ACC NAME: " + indivPost.getUserId());
                    postsDB.add(indivPost);
                    System.out.println("[3] ACC NAME: " + indivPost.getUserId());
                }

                posts.addAll(postsDB);
                mAdapter.notifyDataSetChanged();
            }

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

            }
        });
    }

我希望显示新数据,来自用户的数据与帖子相结合。

I expected to be printed:
[1] ACC NAME John
[2] ACC NAME John
[3] ACC NAME John
but it's actually 
[2] BniepYpQuh6VgMF6L2
[3] BniepYpQuh6VgMF6L2
[1] John

【问题讨论】:

    标签: java android firebase async-await


    【解决方案1】:

    我希望显示新数据,来自用户的数据与帖子相结合。

    您没有获得新数据的原因是因为您在第二个侦听器中获取用户数据之前将indivPost 添加到列表并通知您的第一个侦听器中的回收视图。这样您就无法实现您想要的,因为您的@987654322 @ 是同步的,而监听器是异步的。更改您的 Firebase 结构以将用户名与帖子一起存储,因此您无需再次调用即可获取用户名。

    【讨论】:

    • 我知道这一点,但修复似乎更像是一种解决方法。问题是即使我这样做,我也想学习如何真正让它发挥作用。有没有办法阻止第一个侦听器直到第二个侦听器完成?如果我得到正确的指示,这就是我想知道和做的事情。
    • @MariusMircea 它不是一种解决方法。假设您有 100k 个帖子,您会调用内部侦听器 100k 次并一直阻止用户吗?我认为这不是更好的方法。
    • 我想你是对的,我只是认为将数据添加到帖子结构不是一个好习惯(从某种意义上说,如果我以后需要其他东西,我会怎么做?添加帖子的数据使它成为一个巨大的 JSON?)感谢您的建议,我会尝试以这种方式修复它。
    猜你喜欢
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多