如何在Firebase-Android中链接2个EventListener,以使第一个EventListener直到第二个EventListener结束才继续?

时间:2019-01-11 19:26:22

标签: java android firebase async-await

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

我找不到任何可在线尝试的东西(除了一些UI阻止的东西,我宁愿远离,因为我是Android新手)。我知道Firebase是异步的,并且Java没有Promise或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

1 个答案:

答案 0 :(得分:1)

  

我希望显示新数据,即来自用户的数据和帖子。

之所以没有获得新数据是因为要在第一个侦听器中添加import { Class } from 'meteor/jagi:astronomy'; import { Behavior } from 'meteor/jagi:astronomy-softremove-behavior'; /** * @class User */ const User = Class.create ({ name: 'User', collection: Meteor.Users, secured: false, fields: { emails: { type: Email, optional: true } }, behaviors: { softremove: { removedFieldName: 'removed', hasRemovedAtField: true, removedAtFieldName: 'removedAt' }, timestamp: { hasCreatedField: true, createdFieldName: 'createdAt', hasUpdatedField: true, updatedFieldName: 'updatedAt' } } }); export default User; 到列表中并通知回收视图,然后才能在第二个侦听器中获取用户数据。这样,您将无法实现所需的目标,因为indivPost是同步的,侦听器是异步的。更改您的Firebase结构以存储带有帖子的用户名,因此您无需再次调用即可获取用户名。