Последовательное чтение данных из Firestore
У меня есть 2 collection в Firestore из которых нужно читать данные последовательно. То есть сначала прочитать document1 из collection 1, а потом на основе document1 вытащить document2 из collection2. Структура базы данных такая: collection1.document1.collection2.document2
Для этого я думал реализовать CompletableFuture, чтобы 2 ассинхронных процесса (получение document1 и получение document2) связать в одну цепочку.
CompletableFuture<ArrayList<QueryDocumentSnapshot>> ReadData(String collectionPath){
final CompletableFuture<ArrayList<QueryDocumentSnapshot>> future = new CompletableFuture<>();
Log.e(TAG,"Future execution has started");
db.collection(collectionPath)
.get()
.addOnCompleteListener(task -> {
Log.e(TAG,"Future execution is in progress");
if (task.isSuccessful()) {
docList.clear();
for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {
docList.add(document);
}
future.complete(docList);
Log.e(TAG,"Future execution has completed");
} else {
Log.e("FirebaseDB", "Error getting documents: ", task.getException());
Log.e(TAG,"Future execution failed");
future.complete(null);
}
});
return future;
}
Но это не работает: мой future пролетает сразу до строки return future, при этом блок с addOnCompleteListener зависает. Я предполагаю, что это происходит из-за того, что addOnCompleteListener - это ещё один ассинхронный процесс, который выполняется внутри моего future.
Подскажите, пожалуйста, как мне переделать
db.collection(collectionPath)
.get()
.addOnCompleteListener(task -> {...})
в CompletableFuture, чтобы я смог выстроить цепочку последовательных чтений из db(Firestore)?
Ответы (1 шт):
Странно, что никто не знает ответа. Спустя некоторое время я сам нарыл ответ:
Task<?> docTask = db.collection(collectionPath).get();
Tasks.whenAllComplete(docTask).addOnCompleteListener(new OnCompleteListener<List<Task<?>>>() {
@Override
public void onComplete(@NonNull Task<List<Task<?>>> task) {
....... }
То есть первый запрос в базу данных объявляем как Task А затем у объекта Tasks есть whenAllComplete, где через запятую можно указать несколько таких квери с типом Task (у меня просто он 1), и на этот же Tasks вешаем OnCompleteListener, который выполнится только тогда, когда все таски внутри whenAllComplete завершены. Кстати, внутрь этого OnCompleteListener можно поместить ещё несколько тасков и там же внутри применить whenAllComplete и новый OnCompleteListener. Таким образом можно выстраивать процессы в цепочку.
Может быть будет кому-то полезно ))