Firestore не запрашивает вторую коллекцию - PullRequest
0 голосов
/ 06 февраля 2019

Я новичок в базе данных android studio и firestore, и у меня возникли проблемы с запросом моей второй коллекции firestore.Как видно из названия, я запрашиваю две коллекции, первая из них:

enter image description here

с кодом:

    firestore = FirebaseFirestore.getInstance();
    FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
            .build();
    firestore.setFirestoreSettings(settings);
    firestore.collection("Obiective").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {

            //<--------- Check if firestore entry is already downloaded into file --------->
            SingletonObjectivesId.getInstance().getIds().clear();
            for (QueryDocumentSnapshot document : task.getResult()) {
                Log.d(TAG, task.getResult().size() + " number of documents");
                SingletonObjectivesId.getInstance().setSize(task.getResult().size());

                if(document.exists() && document != null) { ...

ивторая коллекция имеет следующий формат:

enter image description here

с кодом:

        firestore.collection("Routes")
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {

                        Log.d(TAG, task.getResult().size() + " = task.getResult().size()");

                        for (QueryDocumentSnapshot document : task.getResult()) {
                            objectives_id.clear();
                            id_route = document.getId();

                            if(document.exists() && document != null) {
                                Map<String, Object> map = document.getData();
                                for (Map.Entry<String, Object> entry : map.entrySet()) {
                                    String field_name = entry.getKey() + "";
                                    String id = document.getString(field_name) + "";
                                    objectives_id.add(id);
                                }
                            }
                            routes.add(new Route(objectives, objectives_id, id_route));
                        }
                    } else {
                        Log.d(TAG, "Error getting documents: ", task.getException());
                    }
                }
            });

Как видно из второго кодая добавил Log.d (после if (task.isSuccessful ())), который будет отображать количество документов.В моем случае первый запрос Log.d возвращает 3, а второй возвращает 0, несмотря на то, что у меня там 2 документа.Как я могу получить доступ к этим 2 документам?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

После того, как я выполнил шаги из видео, я обновил код следующим образом:

У меня есть глобальная переменная firestore, созданная в начале моего класса

private FirebaseFirestore firestore;

У меня есть дваметоды readDataObjective и readDataRoute и два интерфейса FirestoreCallback и FirestoreCallbackRoutes

readDataRoutes

    private void readDataRoute(FirestoreCallbackRoute firestoreCallbackRoute){
    firestore.collection("Trasee").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        for (QueryDocumentSnapshot document : task.getResult()) { ...

readDataObjective

   private void readDataObjective(FirestoreCallback firestoreCallback){
    firestore.collection("Obiective").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {   
                SingletonObjectivesId.getInstance().getIds().clear();
                for (QueryDocumentSnapshot document : task.getResult()) { ...

Интерфейсы

private interface FirestoreCallback{
    void onCallback(ArrayList<Objective> list);
}

private interface FirestoreCallbackRoute{
    void onCallback(ArrayList<Route> list);
}

И в onCreя называю readDataObjective и readDataRoute следующим образом

firestore = FirebaseFirestore.getInstance();
    FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder().build();
    firestore.setFirestoreSettings(settings);

    readDataObjective(new FirestoreCallback() {
        @Override
        public void onCallback(ArrayList<Objective> list) {
            for(Objective item : list){
                //Create plainText Object - delimiter "/~/"
                String data = "Title:" + item.getTitle() + "/~/" +

............................

     } else if(str.contains("Longitude:")){
                            obj.setLongitude(str.substring(10,str.length()));
                        }

                        start = crt + 2;
                    }
                }
                SingletonObjectivesArray.getInstance().getObjectives().add(obj);
            }

            readDataRoute(new FirestoreCallbackRoute() {
                @Override
                public void onCallback(ArrayList<Route> list) {
                    Log.d(TAG, 2 + " ");
                    ArrayList<Objective> routeObjectives = new ArrayList<>();

                    for (int i = 0; i < list.size(); i++) {
                        routeObjectives.clear();
                        for (int j = 0; j < SingletonObjectivesArray.getInstance().getObjectives().size(); j++){ ...

С упоминанием, что readDataRoute вызывается внутри readDataObjective, в конце его.

Я заметил, что проблема не только во втором запросе, но и в первом.Я добавил новый документ в первую коллекцию, и после выполнения кода первый запрос вернет старые данные (без моей новой записи).

0 голосов
/ 06 февраля 2019

API Firebase являются асинхронными, это означает, что метод onComplete() возвращается сразу после его вызова, а обратный вызов из Задачи, которую он возвращает, будет вызван через некоторое время.Там нет никаких гарантий о том, сколько времени это займет.Таким образом, получение этих данных может занять от нескольких сотен миллисекунд до нескольких секунд.Поскольку этот метод возвращает немедленно, количество документов, которые вы пытаетесь зарегистрировать, еще не заполняется из обратного вызова.

По сути, вы пытаетесь использовать значение синхронно из асинхронного API.Это не очень хорошая идея.Вы должны обрабатывать API-интерфейсы асинхронно, как и планировалось.

Быстрое решение этой проблемы - переместить код, который запрашивает вторую коллекцию, в первый обратный вызов (внутри метода onComplete()) так называемых вложенных запросов,в противном случае я рекомендую вам посмотреть последнюю часть моего ответа от этого поста , в котором я объяснил, как это можно сделать с помощью пользовательского обратного вызова.Вы также можете взглянуть на это видео для лучшего понимания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...