Firestore замечает, что все загружено

Структура моей базы данных Firestore выглядит так:

  1. ... Коллекция с обычными объектами.

  2. ... Коллекция с объектами тренировки. С атрибутами

    -> RoutineKey: хранит ключ процедуры, из которой создана тренировка.

    -> ExerciseEntryKeys: ArrayList<String> ключей ExerciseEntry из тренировки

  3. ... Коллекция с объектами ExerciseEntries.

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

for (final DocumentSnapshot doc : documentSnapshots.getDocuments()) {

                    final WorkoutSNR workout = doc.toObject(WorkoutSNR.class);
                    workout.setKey(doc.getId());

                    workoutsFromRoutine.add(workout);

                    fm.getColRefExerciseEntries().whereEqualTo("workoutKey", workout.getKey()).get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                        @Override
                        public void onSuccess(QuerySnapshot documentSnapshots) {
                            if (documentSnapshots.isEmpty()) {
                                prg.setVisibility(View.GONE);
                                processData();
                            } else {

                                for (int i = 0; i < workout.getExcersiseEntryKeys().size(); i++) {

                                    fm.getDocRefExerciseEntrie(workout.getExcersiseEntryKeys().get(i)).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                                        @Override
                                        public void onSuccess(DocumentSnapshot documentSnapshot) {

                                            final ExcersiseEntrySNR entry = documentSnapshot.toObject(ExcersiseEntrySNR.class);
                                            entry.setKey(documentSnapshot.getId());

                                            workout.getExcersises().add(entry);

                                            processData();
                                            prg.setVisibility(View.GONE);

                                            Collections.sort(workout.getExcersises(), new Comparator<ExcersiseEntrySNR>() {
                                                @Override
                                                public int compare(ExcersiseEntrySNR e1, ExcersiseEntrySNR e2) {
                                                    if (e1.getPosition() < e2.getPosition()) {
                                                        return -1;
                                                    } else if (e1.getPosition() > e2.getPosition()) {
                                                        return 1;
                                                    } else {
                                                        return 0;
                                                    }
                                                }
                                            });
                                        }
                                    });
                                }
                            }
                        }
                    });
                }
            }
        });

Это работает так, как должно, но, как вы можете видеть, я звоню:

processData();
    prg.setVisibility(View.GONE);

    Collections.sort(workout.getExcersises(), new Comparator<ExcersiseEntrySNR>() {
        @Override
        public int compare(ExcersiseEntrySNR e1, ExcersiseEntrySNR e2) {
            if (e1.getPosition() < e2.getPosition()) {
                return -1;
            } else if (e1.getPosition() > e2.getPosition()) {
                return 1;
            } else {
                return 0;
            }
        }
    });

Всегда, когда ExerciseEntry был успешно загружен. В этом нет необходимости, и я хочу вызывать этот код только один раз (Every ExerciseEnry для каждой тренировки в программе).

Как лучше всего заметить, что все загружено? Предоставляет ли Firestore какую-либо функцию для этого?

Я пробовал иметь целое число, которое подсчитывает количество успешных загрузок ExerciseLoads и Workout, но я могу получить доступ только к конечным переменным внутри вложенного класса (так оно и называется?).

Итак, в чем основной вопрос, вы хотите знать, когда данные полностью загружены из базы данных?

Alex Mamo 23.04.2018 21:51

Да, точно. Извините, если это было непонятно

Jonas 24.04.2018 11:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

How do I know when the data is completely loaded from the database?

Вы можете добавить флаг к каждому объекту Routine и Workout со значением false и, как только вы загрузите эти объекты, установить значение true, но это не то, как все работает с Firestore. Вы не можете узнать, когда объект из базы данных будет загружен, потому что Cloud Firestore is also a realtime database и получение данных может никогда не завершиться. Вот почему он назван realtime database, потому что в любой момент данные в этих объектах Routine и Workout могут быть изменены, свойства могут быть добавлены или удалены.

Вы можете использовать CompletionListener только тогда, когда вы используете данные написать или Обновить, и вы будете уведомлены, когда операция будет подтверждена серверами базы данных, но вы не можете использовать этот интерфейс при чтении данных.

Так я ничего не могу там сделать? Я имею в виду, что сортировка моего ArrayList каждый раз, когда объект загружается, не подходит.

Jonas 24.04.2018 14:34

Сортировка ArrayList каждый раз при загрузке объекта не означает, что вы завершили загрузку данных из базы данных. Поскольку в любой момент ваша база данных может быть изменена, вы никогда не сможете сказать, что ваша загрузка завершена. Но это не недостаток, так работает база данных в реальном времени.

Alex Mamo 24.04.2018 14:42

Но я не использую ChangeListener или что-то еще. Я просто загружаю документы, и даже если в базе данных есть какие-либо изменения, я не получаю дополнительных документов. Поэтому я не понимаю, почему я не могу заметить, что загрузил все существующие документы в то время, когда я начинаю загружаться.

Jonas 24.04.2018 15:16

Когда вы используете вызов get (), это означает, что вы получаете данные из базы данных, и нет никакого смысла говорить, что вы закончили загрузку. Обратите внимание, что ни КоллекцияСсылка, ни DocumentReference не имеют метода, который позволил бы вам достичь этого. И как я уже упоминал в своем ответе, вы можете добиться этого только при использовании операции записи.

Alex Mamo 24.04.2018 15:52

Хорошо, поэтому Firestore не предоставляет мне никакой функции для этого, но я должен иметь возможность иметь 'int count' для тренировок и упражнений и проверять в onSuccess, равно ли количество тренировок размеру QuerySnapshot и если количество упражнений равно размеру ExerciseEntryKeys, верно? Проблема в том, что я не могу увеличить переменную счетчика внутри onSuccess, потому что я могу получить доступ только к конечным переменным ...

Jonas 24.04.2018 20:59

Нет. Если вы хотите подсчитать количество документов в коллекции, это - это то, как вы можете это сделать, но, к сожалению, я боюсь, что это не решит проблему, связанную с завершением загрузки данных. Что касается конечных переменных, просто объявите, что эта переменная имеет локальную область видимости.

Alex Mamo 24.04.2018 21:20

вы сказали в этой теме, что нет метода getDocumentCount (), но это не «documentSnapshots.getDocuments (). size ()» (из QuerySnapshot)? Если да, то я не понимаю, почему подсчет моих успешных нагрузок не работает. Мне кажется, что с базой данных в реальном времени это намного проще, возможно, мне стоит снова вернуться к этой базе данных, хотя мне действительно нравится концепция коллекции / документа. Спасибо за вашу помощь, кстати.

Jonas 24.04.2018 21:33

Да, вы можете подсчитать количество документов с помощью task.getResult().size(), но это не значит, что вы узнаете, когда загрузка данных завершится. Я не сказал, что пересчитать документы не получится, я просто сказал, что это поможет вам в том, что вы хотите. Представьте, что в коллекции есть 100 документов. Вы используете метод подсчета этих документов, но тем временем добавляется один новый документ. Результатом вашего метода будет 100, но реальный номер документа - 101. Таким образом, вы получите несогласованные данные. Таким образом, вы не можете узнать, когда загрузка данных завершилась.

Alex Mamo 24.04.2018 21:47

Пожалуйста. Надеюсь, я был достаточно ясен, чтобы вы поняли эту концепцию. Вы также можете дождаться других ответов, но если вы считаете, что мой ответ вам помог, подумайте о том, чтобы принять его и проголосовать. Спасибо!

Alex Mamo 24.04.2018 21:48

Все в порядке? Могу я помочь вам с другой информацией?

Alex Mamo 25.04.2018 10:11

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

Jonas 25.04.2018 20:13

Итак, если кому-то интересно, каково мое Решение в конце, вот мой текущий Код:

fm.getColRefWorkoutSNR().whereEqualTo("routineKey", routineKey).get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
            @Override
            public void onSuccess(QuerySnapshot documentSnapshots) {
                final int workoutSize = documentSnapshots.getDocuments().size();
                for (final DocumentSnapshot doc : documentSnapshots.getDocuments()) {

                    final WorkoutSNR workout = doc.toObject(WorkoutSNR.class);
                    workout.setKey(doc.getId());

                    workoutsFromRoutine.add(workout);

                    fm.getColRefExerciseEntries().whereEqualTo("workoutKey", workout.getKey()).get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                        @Override
                        public void onSuccess(QuerySnapshot documentSnapshots) {
                            if (documentSnapshots.isEmpty()) {
                                prg.setVisibility(View.GONE);
                                processData();
                            } else {

                                if (workout.getExcersiseEntryKeys().size() > 0) {
                                    for (int i = 0; i < workout.getExcersiseEntryKeys().size(); i++) {

                                        fm.getDocRefExerciseEntrie(workout.getExcersiseEntryKeys().get(i)).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                                            @Override
                                            public void onSuccess(DocumentSnapshot documentSnapshot) {

                                                final ExcersiseEntrySNR entry = documentSnapshot.toObject(ExcersiseEntrySNR.class);
                                                entry.setKey(documentSnapshot.getId());

                                                workout.getExcersises().add(entry);

                                                if (workout.getExcersises().size() == workout.getExcersiseEntryKeys().size()) {
                                                    increaseFullyLoadedWorkouts();
                                                }

                                                if (fullyLoadedWorkouts == workoutSize) {
                                                    processData();
                                                    prg.setVisibility(View.GONE);
                                                }
                                            }
                                        });
                                    }
                                } else {
                                    increaseFullyLoadedWorkouts();
                                    if (fullyLoadedWorkouts == workoutSize) {
                                        processData();
                                        prg.setVisibility(View.GONE);
                                    }
                                }

                            }
                        }
                    });
                }
            }
        });

Как видите, я проверяю, все ли упражнения загружены для тренировки, и если это так, я увеличиваю счетчик «fullLoadedWorkout». Затем я проверяю, соответствует ли счетчик размеру тренировки, и если это так, я знаю, что я «полностью» загрузил свои данные.

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

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