Получение данных из базы данных Firebase с нескольких путей

У меня проблема с получением данных из Firebas eDatabase по разным путям. Я пишу клон Endomondo, и у меня есть следующая структура базы данных:

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

Теперь я хочу перечислить все тренировки моих друзей во вкладке ленты. Итак, чтобы сделать это, мне нужно сделать три вещи.

1) Просмотрите мой профиль (user_1), чтобы получить идентификаторы всех моих друзей.

2) Когда у меня есть эти идентификаторы, мне нужно перебирать их профили, чтобы отобразить их имена.

3) Перебирайте тренировки, чтобы получить все тренировки моих друзей. А теперь я хочу поместить всю эту информацию в один объект, скажем «FriendWorkout», который будет выглядеть так:

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

И поместите все эти объекты в список, чтобы я мог передать их адаптеру.

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" : "[email protected]",
      "firstName" : "Jadwiga",
      "friends" : {
        "CTS134a7vtMWcBs7N2ynDKSyKj23" : true,
        "DoXUtoa7vtMWcBs7N2ynDKSyKj23" : true
      },
      "lastWorkout" : "-LRGN8H6a1esdUPvb-ve",
      "surname" : "Szalony"
    },
    "CTS134a7vtMWcBs7N2ynDKSyKj23" : {
      "avatarUrl" : "none",
      "email" : "[email protected]",
      "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"
      }
    }
  }
}

Это могло быть очень просто. Покажите нам свою реальную структуру базы данных в виде файла JSON или хотя бы в виде снимка экрана.

Alex Mamo 15.11.2018 11:21

@AlexMamo обновил пост с помощью JSON.

northenofca 15.11.2018 11:31

Хорошо, я напишу тебе ответ прямо сейчас.

Alex Mamo 15.11.2018 11:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
3
1 052
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

То, что вам нужно, можно решить, запросив базу данных три раза: один раз, чтобы получить friendUid, второй, чтобы получить соответствующий names, и третий, чтобы получить объекты Workout соответствующих друзей. Поэтому используйте следующие строки кода:

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);

Большое спасибо! У меня есть еще один вопрос. Допустим, я хочу добавить все эти новые объекты FriendWorkout в список List<FriendWorkout > workouts = new ArrayList<>();, а затем уведомить адаптер о том, что у него есть новые данные для загрузки. Как это сделать по-хорошему, чтобы избежать лишних обращений к адаптеру?

northenofca 15.11.2018 12:46

В общем, другие вопросы, вытекающие из исходного вопроса, следует рассматривать как новые вопросы и должны быть добавлены сюда отдельно в stackoverflow. Видя, что вы новый участник, я только что обновил свой ответ вашим новым запросом. Пожалуйста, посмотрите мой обновленный ответ.

Alex Mamo 15.11.2018 12:58

Если вы считаете, что мой ответ и дополнения помогли вам, примите его, нажав на галочку (✔️) слева под стрелками голосования. Должен поменять цвет на зеленый. Я бы оценил это. Спасибо!

Alex Mamo 15.11.2018 12:59

Ваши ответы мне очень помогли. Спасибо. Я буду держать в памяти все ваши советы / комментарии на будущее! Спасибо, мистер Алекс.

northenofca 15.11.2018 19:04

Другие вопросы по теме