Android как запустить процесс, когда два асин c процесса завершают sh выполнение - PullRequest
0 голосов
/ 23 января 2020

Я новичок в фоновых задачах Android. Я использую Firestore для выполнения следующих задач:

  1. Чтение документа. https://firebase.google.com/docs/firestore/query-data/get-data

    DBInstance.collection("restaurants")
                .get()
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
    
                        for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {
    
                         // some other code
    
                        }
                    } else {
                        Log.d(TAG, "Error getting documents: ", task.getException());
                    }
    
    
                });
    
  2. Прослушивание обновлений в реальном времени другого документа. https://firebase.google.com/docs/firestore/query-data/listen

    final DocumentReference docRef = DBInstance.collection("users").document(FirebaseAuth.getInstance().getCurrentUser().getUid());
        docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
            @Override
            public void onEvent(@Nullable DocumentSnapshot snapshot,
                                @Nullable FirebaseFirestoreException e) {
                if (e != null) {
                    Log.w(TAG, "Listen failed.", e);
                    return;
                }
    
                String source = snapshot != null && snapshot.getMetadata().hasPendingWrites()
                        ? "Local" : "Server";
    
                if (snapshot != null && snapshot.exists()) {
                    Log.d(TAG, source + " data: " + snapshot.getData());
    
                    // some other code is run
    
                } else {
                    Log.i(TAG,"no snapshot found");
                }
            }
        });
    

Поскольку это асинхронные процессы, они выполняются одновременно (примерно).

Я хочу вызвать независимый метод, когда 1. завершено И когда 2. возвращает ненулевой снимок. Поэтому, когда some other code комментарии выше были завершены.

Итак, я, по сути, хочу некоторый фоновый процесс, который бездействует / прослушивает два вышеупомянутых условия и выполняет задачу / вызывает метод, который обновляет определенные функции пользовательского интерфейса.

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

решения, которые, кажется, работают (частично предложенные Nehal)

Это тот же код, что и выше, с заполненными пробелами

DBInstance.collection("restaurants")
            .get()
            .addOnCompleteListener(task -> {
                if (task.isSuccessful()) {

                    for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {

                     restaurantsLoaded = true;
                     updateUI();

                    }
                } else {
                    Log.d(TAG, "Error getting documents: ", task.getException());
                    restaurantsLoaded = false;
                }


            });


    final DocumentReference docRef = DBInstance.collection("users").document(FirebaseAuth.getInstance().getCurrentUser().getUid());
docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
    @Override
    public void onEvent(@Nullable DocumentSnapshot snapshot,
                        @Nullable FirebaseFirestoreException e) {
        if (e != null) {
            Log.w(TAG, "Listen failed.", e);
            return;
        }

        String source = snapshot != null && snapshot.getMetadata().hasPendingWrites()
                ? "Local" : "Server";

        if (snapshot != null && snapshot.exists()) {
            Log.d(TAG, source + " data: " + snapshot.getData());

            usersSnapshotTriggered = true;
            udpateUI();

        } else {
            Log.i(TAG,"no snapshot found");
        }
    }
});


public void updateUI(){
    if(usersSnapshotTriggered && restaurantsLoaded){
        // perform the updates
    }
}

Ответы [ 2 ]

1 голос
/ 23 января 2020

Я хочу запустить независимый метод, когда оба 1. и 2. были завершены

В вашем первом примере, добавив полного слушателя, вы всегда сможете знать, когда операция завершена. Если task.isSuccessful() возвращает true, вы точно знаете, что операция завершена. Кроме того, вы также можете позвонить getResult(), чтобы получить элементы, которые являются частью вашей коллекции restaurants. Кроме того, следующая строка кода:

DBInstance.collection("restaurants")
        .get()

Возвращает объект Task<QuerySnapshot>. Если у вас было два разных запроса, вы могли бы передать оба объекта Task методу Tasks whenAllSuccess () , как объяснено в моем ответе из следующего поста:

Таким образом, вы сможете узнать, когда обе операции завершены. Однако при использовании второго решения вы не можете знать, когда получение данных из базы данных завершено, поскольку Cloud Firestore - это база данных в реальном времени, и получение данных может никогда не завершиться. Вот почему она называется базой данных реального времени, потому что в любой момент ее можно изменить, добавить или удалить элементы.

Единственный способ частично узнать, есть ли у вас все данные в конкретной коллекции, - это выполнить запрос типа single value . Даже в этом случае данные могут измениться после вызова этого слушателя, поэтому все, что у вас есть на самом деле, - это snapshot в определенный момент времени.

В заключение, единственное решение, которое у вас есть, - это использовать whenAllSuccess() и передать два или даже больше Task объектов.

Я кратко прочитал о BroadcastReciever. Это актуально?

Нет, это не так. Согласно документам, класс BroadcastReceiver :

Базовый класс для кода, который получает и обрабатывает намерения широковещания, отправленные Context.sendBroadcast (Intent).

Итак, дело не в этом.

или, может быть, я могу создать пользовательский прослушиватель, работающий в фоновом потоке?

Клиент Cloud Firestore уже запускает все сетевые операции в фоновом потоке. Это означает, что все операции выполняются без блокировки вашего основного потока. Размещение в фоновом потоке не дает никаких дополнительных преимуществ.

1 голос
/ 23 января 2020

Вы можете попробовать следующее решение: объявить глобальную переменную int, увеличить ее значение в слушателе firebase и вызвать someMethod () из обоих слушателей.

private int count=0;

DBInstance.collection("restaurants")
            .get()
            .addOnCompleteListener(task -> {
                if (task.isSuccessful()) {

                    for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {

                     // some other code

                    }
                    count++;
                    someMethod();
                } else {
                    Log.d(TAG, "Error getting documents: ", task.getException());
                }


            });


final DocumentReference docRef = DBInstance.collection("users").document(FirebaseAuth.getInstance().getCurrentUser().getUid());
    docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
        @Override
        public void onEvent(@Nullable DocumentSnapshot snapshot,
                            @Nullable FirebaseFirestoreException e) {
            if (e != null) {
                Log.w(TAG, "Listen failed.", e);
                return;
            }

            String source = snapshot != null && snapshot.getMetadata().hasPendingWrites()
                    ? "Local" : "Server";

            if (snapshot != null && snapshot.exists()) {
                Log.d(TAG, source + " data: " + snapshot.getData());

                // some other code is run
                    count++;
                    someMethod();
                    //Note : this method will call as many times as there is change in this data , so you have to handle according to your requirement
            } else {
                Log.i(TAG,"no snapshot found");
            }
        }
    });


private void someMethod(){
    if(count>=2){
       //execute your code
   }
}

Надеюсь, это поможет !!

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