Getting data from Firebase Database from multiple paths

Viewed 1294

I have a problem with getting data from Firebas eDatabase from multiple paths. I am writing an Endomondo clone and I have a database structure as follows:

users:
    user_1:
        name:
        ....
        friends:
            user_2
            user_3
    user_2:
        ...
workouts:
    user_1:
        workout_1:
            distance:
            duration:
            path:
            etc.
    user_2:

Now I want to list all workouts of my friends in feed tab. So to do it I need to do three things.

1) Iterate over my profile (user_1) to get all my friends ids.

2) When I have those ids, I need to iterate over their profiles to get their names to display.

3) Iterate over workouts to get all workouts of my friends.
And now I want to put all this information in one object, lets say "FriendWorkout" which would look like:

FriendWorkout:
    String friendName;
    Workout workout; // contains all workout data(path, time, distance)

And put all of those object in the list so I can pass it to the adapter.

JSON:

{
  "users" : {
    "BLhXU5eJGtZayRrUGYTrGiImg313" : {
      "avatarUrl" : "https://firebasestorage.googleapis.com/v0/b/alphaui-40ee2.appspot.com/o/avatars%2Favatars%2FBLhXU5eJGtZayRrUGYTrGiImg313.jpg?alt=media&token=c6b00937-6970-4f43-8ea4-b9add33c43e1",
      "email" : "xhh@gmail.com",
      "firstName" : "Jadwiga",
      "friends" : {
        "CTS134a7vtMWcBs7N2ynDKSyKj23" : true,
        "DoXUtoa7vtMWcBs7N2ynDKSyKj23" : true
      },
      "lastWorkout" : "-LRGN8H6a1esdUPvb-ve",
      "surname" : "Szalony"
    },
    "CTS134a7vtMWcBs7N2ynDKSyKj23" : {
      "avatarUrl" : "none",
      "email" : "ofca@wp.pl",
      "firstName" : "Leokadia",
      "friends" : {
        "BLhXU5eJGtZayRrUGYTrGiImg313" : true
      },
      "lastWorkout" : "dasdsa",
      "surname" : "Fin"
    }
  },
  "workouts" : {
    "BLhXU5eJGtZayRrUGYTrGiImg313" : {
      "-LRGN3sEJgrNxRH3Hf6j" : {
        "date" : "Wed, 14 Nov 2018 09:39:41",
        "distance" : 0,
        "duration" : "0:00",
        "workoutName" : "Running"
      },
      "-LRGN68Z_s5dUjlkuhB-" : {
        "date" : "Wed, 14 Nov 2018 09:39:50",
        "distance" : 0,
        "duration" : "0:00",
        "workoutName" : "Running"
      }
    },
    "DoXUtoa7vtMWcBs7N2ynDKSyKj23" : {
      "-LRGSafxbmKWGLy5x-Kd" : {
        "date" : "Wed, 14 Nov 2018 10:03:50",
        "distance" : 0,
        "duration" : "0:02",
        "workoutName" : "Running"
      }
    }
  }
}
1 Answers

What you need can be solved by querying the database three times, once to get the friendUid, second to get the corresponding names and third to get the Workout objects of the corresponding friends. So please use the following lines of code:

String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference friendsRef = rootRef.child("users").child(uid).child("friends");
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String friendUid = ds.getKey();

            DatabaseReference friendUidRef = rootRef.child("users").child(friendUid);
            ValueEventListener eventListener = new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    for(DataSnapshot ds : dataSnapshot.getChildren()) {
                        String firstName = ds.child("firstName").getValue(String.class);
                        String surname = ds.child("surname").getValue(String.class);
                        String friendName = firstName + " " + surname;
                        Log.d(TAG, friendName);

                        DatabaseReference friendUidWorkoutsRef = rootRef.child("workouts").child(friendUid);
                        ValueEventListener listener = new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                List<FriendWorkout > workouts = new ArrayList<>(); //List added
                                for(DataSnapshot ds : dataSnapshot.getChildren()) {
                                    Workout workout = ds.getValue(Workout.class);
                                    Log.d(TAG, workout.getWorkoutName());

                                    //Create an object of FriendWorkout as needed
                                    FriendWorkout friendWorkout = new FriendWorkout(friendName, workout);
                                    workouts.add(friendWorkout); //Add object to the list
                                }
                                ListView listView = (ListView) findViewById(R.id.list_view);
                                ArrayAdapter<Data> arrayAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, list);
                                listView.setAdapter(arrayAdapter); //Set the adapter
                            }

                            @Override
                            public void onCancelled(@NonNull DatabaseError databaseError) {
                                Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
                            }
                        };
                        friendUidWorkoutsRef.addListenerForSingleValueEvent(listener);
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {
                    Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
                }
            };
            friendUidRef.addListenerForSingleValueEvent(eventListener);
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
    }
};
friendsRef.addListenerForSingleValueEvent(valueEventListener);
Related