web-dev-qa-db-fra.com

Firebase Firestore récupère les données de manière synchrone/sans rappel

J'utilise Cloud Firestore dans un thread distinct de mon application Android. Je ne souhaite donc pas utiliser les écouteurs OnSuccessListener et OnFailureListener pour s'exécuter dans un autre thread. Puis-je faire en sorte que mon thread attende le résultat (et intercepte des exceptions si nécessaire)?

Actuellement, le code d'interrogation ressemble à ceci:

FirebaseFirestore.getInstance().collection("someCollection").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
    @Override
    public void onSuccess(QuerySnapshot documentSnapshots) {
         // do something on the UI thread with the retrieved data
         }
    });

Ce que j'aimerais avoir:

FirebaseFirestore.getInstance().collection("someCollection").getAndWaitForResult();
//Block the thread and wait for result, no callbacks. 
//getAndWaitForResult() is not a real function, just something to describe my intention.

J'avais l'habitude de travailler avec Parse Server avant, et c'était assez trivial là-bas.

6
Dmitri Borohhov

Vous pouvez charger des données de manière synchrone, car une DocumentReference.get() renvoie une Task. Vous pouvez donc simplement attendre pour cette tâche. 

Si je fais quelque chose comme:

    val task: Task<DocumentSnapshot> = docRef.get()

alors je peux attendre que cela se termine en faisant 

val snap: DocumentSnapshot = Tasks.await(task)

Ceci est utile lorsque vous combinez d'autres opérations après le get () avec des continuations qui peuvent prendre un peu de temps:

val task: Task = docRef.get (). continueWith (exécuteur, suite)

Ci-dessus, j'exécute une continuation sur un exécuteur séparé et je peux attendre que tout soit terminé avec Tasks.await(task).

Voir https://developers.google.com/Android/guides/tasks

Remarque: vous ne pouvez pas appeler Tasks.await () sur votre thread principal. L'API des tâches vérifie spécifiquement cette condition et lève une exception.

Il existe une autre façon de fonctionner de manière synchrone, en utilisant des transactions. Voir cette question.

11
Dutch Masters

Vous pouvez faire quelque chose comme ceci sur le fil principal...

YourObject yourObject = (YourObject)new RunInBackground().
                          execute("someCollection","someDocument").get()

Et le thread d'arrière-plan est ...

public class RunInBackground extends AsyncTask {

  @Override
  protected Object doInBackground(Object[] objects) {

    Task<DocumentSnapshot> documentSnapshotTask = FirebaseFirestore.getInstance().
             collection((String) objects[0]).document((String) objects[1]).get();

    YourObject obj=null;

    try {
        DocumentSnapshot documentSnapshot = Tasks.await(documentSnapshotTask);

        obj = new YourObject();
        obj.setter(documentSnapshot.get("your field"));

    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    return obj;
  }
}
0
GN Reddy