Firebase Android: come leggere da diversi riferimenti in sequenza

In una delle mie attività su Android ho bisogno di eseguire più query a Firebase per mostrare finalmente qualcosa all’utente.

In sintesi, ho bisogno di controllare il riferimento degli utenti per verificare quale fase del corso si trova attualmente, quindi ho bisogno di leggere il contenuto del corso per caricarlo.

Quello che sto facendo attualmente è che ho due listener nidificati come questo:

ref1.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { ref2.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { //do the work } }); } }); 

C’è un modo migliore per fare queste domande quando ne hai bisogno in sequenza?

TL; DR

Proprio come Parse ha fatto con i bulloni , Google ha anche fornito un quadro delle attività che implementa le promesse di JavaScript . Quindi, invece di nidificare i listener, è ansible creare una sequenza di attività.

Il risultato verrà inviato a addOnSuccessListener se tutte le attività vengono eseguite correttamente.

Se uno di essi non riesce durante l’esecuzione del caso d’uso, la sequenza verrà interrotta e l’eccezione verrà passata a addOnFailureListener .

 public Task execute() { return Tasks.forResult(null) .then(new GetUser()) .then(new GetCourse()); } public void updateInBackground() { Tasks.forResult(null) .then(new GetUser()) .then(new GetCourse()) .addOnSuccessListener(this) .addOnFailureListener(this); } @Override public void onFailure(@NonNull Exception error) { Log.e(TAG, error.getMessage()); } @Override public void onSuccess(Customer customer) { // Do something with the result } 

Descrizione

Supponiamo di voler scaricare due oggetti di tipo User e Course da Firebase.

È necessario creare la prima attività della sequenza utilizzando l’ API Tasks . Le tue opzioni sono:

  • Creare un’attività con successo utilizzando Tasks.forResult
  • Creare una TaskCompletionSource , impostare i valori dei risultati o delle eccezioni, quindi restituire un’attività.
  • Crea un’attività da un callable .

Preferisco la prima opzione per la maggior leggibilità del codice dovuta. Se è necessario eseguire le attività nel proprio esecutore, è necessario utilizzare la prima o la seconda opzione.

Ora creiamo due attività di Continuation due scaricate ciascuna:

 class GetUser implements Continuation> { @Override public Task then(Task task) { final TaskCompletionSource tcs = new TaskCompletionSource(); ref1.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onCancelled(DatabaseError error) { tcs.setException(error.toException()); } @Override public void onDataChange(DataSnapshot snapshot) { tcs.setResult(snapshot.getValue(User.class)); } }); return tcs.getTask(); } } 

e

 class GetCourse implements Continuation> { @Override public Task then(Task task) { final User result = task.getResult(); final TaskCompletionSource tcs = new TaskCompletionSource(); ref2.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onCancelled(DatabaseError error) { tcs.setException(error.toException()); } @Override public void onDataChange(DataSnapshot snapshot) { tcs.setResult(snapshot.getValue(Course.class)); } }); return tcs.getTask(); } } 

In base alla documentazione , chiamare getResult() e consentire a RuntimeExecutionException di propagarsi per propagare l’errore dall’attività completata.

RuntimeExecutionException verrà scartato in modo tale che l’attività restituita da continueWith(Continuation) o continueWithTask(Continuation) non riesca con l’eccezione originale.