2017-10-19 9 views
0

Je voudrais mettre en place quelque chose comme un groupe dans Firebase. Si vous avez l'ID de groupe correct, vous pouvez vous joindre.Comment écouter Firebase setValue

Le problème est que les références Firebase existent toujours. Ils sont créés dynamiquement. Pour permettre une vérification d'erreur dans le processus de jonction, je souhaite ajouter l'utilisateur qui a créé la nouvelle entrée de base de données à une table d'utilisateurs.

public void createParty() { 

    // you need to be signed in to create a party 
    assertState(DBState.SignedIn); 

    // create a new party 
    ourPartyDatabaseReference = partiesDatabaseReference.push(); 
    usersDatabaseReference = ourPartyDatabaseReference.child("users"); 

    // write our user to the table of users, now the ourPartyReference actually exists 
    // and if you look for existing users, you will always find at least the original creator 
    Task initTask = usersDatabaseReference.child(user.getUid()).setValue(true); 

Après cela a été fait, j'appelle une méthode d'aide connectToParty pour mettre en place quelques références et changer l'état de la connexion de base de données DBState.Connected. Vous pouvez maintenant prendre la clé de la fête et la transmettre à d'autres utilisateurs. Avec la clé, je veux dire le nom dans Firebase.

Le problème est: Les autres utilisateurs doivent vérifier s'ils ont utilisé une clé valide pour se connecter. Ils le font en vérifiant s'il y a des données sous key/users. La partie n'est donc valide que si le premier utilisateur a été correctement écrit dans la base de données. Parfois, le processus d'écriture prend très longtemps, parfois il semble échouer complètement. J'ai donc mis en place des auditeurs:

Task initTask = usersDatabaseReference.child(user.getUid()).setValue(true); 

initTask.addOnSuccessListener(new OnSuccessListener() { 
    @Override 
    public void onSuccess(Object o) { 
     connectToParty(); 
    } 
}); 

initTask.addOnFailureListener(new OnFailureListener() { 
    @Override 
    public void onFailure(@NonNull Exception e) { 
     changeState(DBState.SignedIn, DBTransition.Failure); 
    } 
}); 

Ceci est couvert par un test. Le test établit une connexion, se connecte et crée une fête. Si la partie est créée dans un délai d'attente spécifique, le test réussit.

9 sur 10 fois cela fonctionne sans problème. Mais parfois, le test échoue.

Cela n'a rien à voir avec le délai d'attente étant trop court. Les rappels de la tâche ne sont simplement pas appelés. J'ai lu que ce rappel ne fonctionne que si votre connexion est en ligne. J'ai ajouté firebaseDatabase.goOnline(); à mon code, juste avant la tâche. Mais cela n'aide pas.

Je suis connecté à Internet via un réseau local. Tous les autres tests passent, et ils doivent également accéder à Firebase. Par exemple pour le processus de connexion.

Quelle est la manière correcte d'écrire une valeur dans la base de données et d'attendre que l'écriture se termine?

+0

Quelle est l'erreur en cas d'échec du test? –

+0

C'est un timeout. J'attends 10 secondes pour le rappel, puis le test échoue. – lhk

+0

Ainsi, aucun des deux n'est appelé – lhk

Répondre

1

Comme le dit offical documentation:

Si vous souhaitez savoir quand vos données ont été commis, vous pouvez ajouter un écouteur d'achèvement. Les deux setValue() et updateChildren() prennent un écouteur d'achèvement optionnel qui est appelé lorsque l'écriture a été validée dans la base de données.

Ceci est un exemple simple:

ref.setValue("I'm writing data to a Firebase database", new Firebase.CompletionListener() { 
    @Override 
    public void onComplete(FirebaseError firebaseError, Firebase firebase) { 
     if (firebaseError != null) { 
      System.out.println("Data could not be saved. " + firebaseError.getMessage()); 
     } else { 
      System.out.println("Data saved successfully."); 
     } 
    } 
}); 
+0

C'est en fait ce que j'ai essayé en premier. Même problème. – lhk

+0

Avez-vous essayé d'utiliser 'setPersistenceEnabled (true);'? Cela signifie que vous pouvez conserver les données de la base de données à deux endroits: en mémoire et/ou sur le disque. Vous pouvez également utiliser 'keepSynced (true)', ce qui signifie que les données de l'application seront toujours à jour avec ce qui se trouve dans la base de données sur le serveur (à condition qu'il existe une connexion réseau). –

+1

J'ai essayé les deux. Le problème ne s'est plus produit. J'ai supprimé le nouveau code, le problème n'est plus survenu. Il est extrêmement difficile de déboguer ce comportement non déterministe. – lhk