Marius Mircea
Marius Mircea

Reputation: 89

How to chain 2 EventListeners in Firebase-Android so that the first one doesn't continue until second one finishes?

I am trying to get some data from Firebase from listener A, then I will search under a different node with listener B based on some ID obtained from listener A, and when I receive the data from listener B, I want to append it to listener A data. Basically I have 2 nodes in Firebase: posts & users. A post has some data, and a userID. When I want to display all posts in the database, I add each one to a RecyclerView, but before I add them to that View, I need to get some user data and only then (combinding these 2 gathered data) add it to the recyclerView.

I could not find anything onlineto try (other than some UI blocking things which I rather stay away as I am new to Android). I know Firebase is async and that Java does not have Promises or async/ await, so IDK what else to try. With my current implementation, I don't achieve what I want (obviously).

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 expect to display new data, data from user combined with the post.

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

Upvotes: 0

Views: 78

Answers (1)

Ali Ahsan
Ali Ahsan

Reputation: 995

I expect to display new data, data from user combined with the post.

Reason you are not getting new data is because you are adding indivPost to list and notifying recycle view in your first listener before getting user data in second listener.This way you can't achieve what you want because your for loop is synchronous and listener is asynchronous. Change your firebase structure to store user's name with posts, So you don't have to make a second call to get usernames.

Upvotes: 1

Related Questions