TrackDave
TrackDave

Reputation: 279

Android Firebase Database retrieving values using multiple listeners

I have a firebase database architecture set up like the docs recommend (data fan out). I have a node with all "athletes" and another node with "teams." I'd like to retrieve the athlete's information from the "athletes" node based on the Athlete's ID inside the "teams" node.

My code looks like this:

if (eventListener == null) {
        eventListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                mAdapter.clear();
                athleteCount = 0;
                final List<Athlete> athletes = new ArrayList<>();
                final long childrenCount = dataSnapshot.getChildrenCount();
                if (childrenCount == 0) {
                    hideProgressBar();
                }
                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    String key = ds.getKey();
                    athleteCount++;
                    if (!TextUtils.isEmpty(key)) {
                        mDatabaseReference.child(Athlete.ATHLETE).child(key)
                                .addListenerForSingleValueEvent(new ValueEventListener() {
                                    @Override
                                    public void onDataChange(DataSnapshot dataSnapshot) {
                                        Athlete athlete = dataSnapshot.getValue(Athlete.class);
                                        if (athlete != null) {
                                            athletes.add(athlete);
                                            if (athleteCount == childrenCount) {
                                                Collections.sort(athletes, new Athlete.AthleteComparator());
                                                mAdapter.setRoster(athletes);
                                                hideProgressBar();
                                            }
                                        }
                                    }
                                    @Override
                                    public void onCancelled(DatabaseError databaseError) {
                                    }
                                });
                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        };
 mDatabaseReference.child("teams")
                .child("-KnyqjH0acSol5cxHLM1")
                .child("athletes")  
                .addValueEventListener(mValueEventListener);

Now this code does work fine, but I do think it's a little over the top to keep adding a listener, then populating my adapter after keeping track that the singleValueListeners have completed. There must be an easier way to do this. I'm asking because I'm also going to need to retrieve other data from another node and that's going be very messy.

If anyone knows a better way please let me know. Thank you.

Here's an image of my architecture: Firebase Database

Upvotes: 0

Views: 459

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598837

I can think of a few approaches:

  1. Extract the code that gets the athlete into a helper method, either with its own callback, or by passing the adapter (or view) along.
  2. Preload all the athletes and then just do a direct lookup.
  3. Duplicate the data that you immediately need about each athlete under the team node. Frequently this is just their name, so you'd have $athleteId: "Athlete's name".

There might be more options, but these are my typical go to's.

Oh btw, the key will never be empty, so this check (and indentation level) is not needed: if (!TextUtils.isEmpty(key)) {.

Upvotes: 1

Related Questions