Firestore通知一切都已加载

时间:2018-04-23 19:47:30

标签: java android firebase google-cloud-firestore

我的Firestore数据库结构如下所示:

  1. ...带有常规对象的集合。

  2. ...带有锻炼对象的集合。使用属性

    - > RoutineKey:存储锻炼的常规关键

    - &GT; ExerciseEntryKeys:来自锻炼的ExerciseEntry键的ArrayList<String>

  3. ...带有ExerciseEntries对象的集合。

  4. 现在我想从一个Routine和一个Workout的ExerciseEntries加载每个Workout。为此,我在加载例程对象后执行以下操作。

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

    Evertime一个ExerciseEntry已成功加载。这是非常不必要的,我想只调用一次所有内容(每个ExerciseEnry用于例程的每个Workout)。

    注意到所有内容的最佳方法是什么? Firestore是否为此提供任何功能?

    我尝试过一个Integer来计算成功的ExerciseLoads和Workout加载次数,但是我只能访问嵌套类中的最终变量(这是它的调用方式吗?)。

2 个答案:

答案 0 :(得分:0)

  

如何知道数据从数据库中完全加载的时间?

您可以为值<div id="result" />的每个RoutineWorkout对象添加一个标记,并在下载这些对象后将值设置为false但是这不是Firestore的工作方式。您无法知道数据库中的对象何时完成下载true并且获取数据可能永远不会完成。这就是为什么命名为Cloud Firestore is also a realtime database,因为在任何momemnt中,可以更改realtime databaseRoutine对象下的数据,可以添加或删除属性。

只有当您更新数据时才能使用Workout,并且当数据库服务器确认操作时您会收到通知但阅读数据时不能使用此界面。

答案 1 :(得分:0)

因此,如果有人想知道我的解决方案到底是什么,这是我现在的代码:

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

                            }
                        }
                    });
                }
            }
        });

正如你所看到的,我检查是否已经加载了每项运动以进行锻炼,如果是这样,我会增加一个&#34; fullLoadedWorkout&#34;计数器。然后我检查计数器是否等于锻炼大小,如果是这样,我知道我有&#34;完全&#34;加载了我的数据。

我知道这不是一个很好的方法,但它是我能想象的唯一解决方案。这在实时数据库中似乎更容易,我仍然考虑切换回它。欢迎任何有关更好方法的建议。