Ce document explique comment utiliser des listes de données dans Firebase. Pour découvrir les principes de base de la lecture et de l'écriture de données Firebase, consultez Lire et écrire des données sur Android.
Obtenir une référence de base de données
Pour lire et écrire des données dans la base de données, vous avez besoin d'une instance de DatabaseReference
:
Kotlin+KTX
private lateinit var database: DatabaseReference // ... database = Firebase.database.reference
Java
private DatabaseReference mDatabase; // ... mDatabase = FirebaseDatabase.getInstance().getReference();
Lire et écrire des listes
Ajouter à une liste de données
Utilisez la méthode push()
pour ajouter des données à une liste dans les applications multi-utilisateurs.
La méthode push()
génère une clé unique à chaque nouvelle requête
enfant est ajouté à la référence Firebase spécifiée. En utilisant ces
générées automatiquement pour chaque nouvel élément de la liste, plusieurs clients peuvent
ajouter des enfants au même emplacement et en même temps sans conflits d'écriture. La clé unique générée par push()
est basée sur un code temporel. Les éléments de la liste sont donc automatiquement triés par ordre chronologique.
Vous pouvez utiliser la référence aux nouvelles données renvoyées par la méthode push()
pour obtenir
la valeur de la clé générée automatiquement ou
définir des données pour l'enfant. Appel en cours
getKey()
sur une référence push()
renvoie la valeur de la
générée automatiquement.
Vous pouvez utiliser ces clés générées automatiquement pour simplifier l'aplatissement de vos données structure. Pour en savoir plus, consultez la section sur la distribution ramifiée des données. exemple.
Écouter les événements enfants
Lorsque vous travaillez avec des listes, votre application doit écouter les événements enfants plutôt que les événements de valeur utilisés pour les objets individuels.
Les événements enfants sont déclenchés en réponse à des opérations spécifiques qui affectent les enfants d'un nœud à partir d'une opération, comme l'ajout d'un enfant via la méthode push()
ou la mise à jour d'un enfant via la méthode updateChildren()
.
Chacun de ces éléments combinés peut être utile pour écouter les modifications apportées à un nœud spécifique
dans une base de données.
Pour écouter les événements enfants sur DatabaseReference
, associez un
ChildEventListener
:
Écouteur | Rappel d'événement | Utilisation habituelle |
---|---|---|
ChildEventListener
| onChildAdded() |
Récupérez des listes d'éléments ou écoutez les ajouts à une liste d'éléments.
Ce rappel est déclenché une fois pour chaque enfant existant, puis à chaque fois qu'un nouvel enfant est ajouté au chemin d'accès spécifié. Le DataSnapshot transmis à l'écouteur contient
les données du nouvel enfant.
|
onChildChanged() |
Écoutez les modifications apportées aux éléments d'une liste. Cet événement se déclenchait chaque fois qu'une
le nœud enfant est modifié, y compris les modifications apportées aux descendants de
le nœud enfant. DataSnapshot transmis à l'événement
"listener" contient les données mises à jour pour l'enfant.
|
|
onChildRemoved() |
Écoutez les éléments supprimés d'une liste. La
DataSnapshot transmis au rappel d'événement contient le
les données de l'enfant supprimé.
|
|
onChildMoved() |
Écoutez les modifications apportées à l'ordre des éléments dans une liste numérotée.
Cet événement est déclenché chaque fois que onChildChanged()
est déclenché par une mise à jour qui entraîne une réorganisation de l'élément enfant.
Il est utilisé avec les données triées avec orderByChild ou orderByValue .
|
Par exemple, une application de blog sur les réseaux sociaux peut utiliser ces méthodes : pour surveiller l'activité liée aux commentaires d'un post, comme illustré ci-dessous:
Kotlin+KTX
val childEventListener = object : ChildEventListener { override fun onChildAdded(dataSnapshot: DataSnapshot, previousChildName: String?) { Log.d(TAG, "onChildAdded:" + dataSnapshot.key!!) // A new comment has been added, add it to the displayed list val comment = dataSnapshot.getValue<Comment>() // ... } override fun onChildChanged(dataSnapshot: DataSnapshot, previousChildName: String?) { Log.d(TAG, "onChildChanged: ${dataSnapshot.key}") // A comment has changed, use the key to determine if we are displaying this // comment and if so displayed the changed comment. val newComment = dataSnapshot.getValue<Comment>() val commentKey = dataSnapshot.key // ... } override fun onChildRemoved(dataSnapshot: DataSnapshot) { Log.d(TAG, "onChildRemoved:" + dataSnapshot.key!!) // A comment has changed, use the key to determine if we are displaying this // comment and if so remove it. val commentKey = dataSnapshot.key // ... } override fun onChildMoved(dataSnapshot: DataSnapshot, previousChildName: String?) { Log.d(TAG, "onChildMoved:" + dataSnapshot.key!!) // A comment has changed position, use the key to determine if we are // displaying this comment and if so move it. val movedComment = dataSnapshot.getValue<Comment>() val commentKey = dataSnapshot.key // ... } override fun onCancelled(databaseError: DatabaseError) { Log.w(TAG, "postComments:onCancelled", databaseError.toException()) Toast.makeText( context, "Failed to load comments.", Toast.LENGTH_SHORT, ).show() } } databaseReference.addChildEventListener(childEventListener)
Java
ChildEventListener childEventListener = new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey()); // A new comment has been added, add it to the displayed list Comment comment = dataSnapshot.getValue(Comment.class); // ... } @Override public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) { Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey()); // A comment has changed, use the key to determine if we are displaying this // comment and if so displayed the changed comment. Comment newComment = dataSnapshot.getValue(Comment.class); String commentKey = dataSnapshot.getKey(); // ... } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey()); // A comment has changed, use the key to determine if we are displaying this // comment and if so remove it. String commentKey = dataSnapshot.getKey(); // ... } @Override public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) { Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey()); // A comment has changed position, use the key to determine if we are // displaying this comment and if so move it. Comment movedComment = dataSnapshot.getValue(Comment.class); String commentKey = dataSnapshot.getKey(); // ... } @Override public void onCancelled(DatabaseError databaseError) { Log.w(TAG, "postComments:onCancelled", databaseError.toException()); Toast.makeText(mContext, "Failed to load comments.", Toast.LENGTH_SHORT).show(); } }; databaseReference.addChildEventListener(childEventListener);
Écouter les événements de valeur
Si l'utilisation d'un ChildEventListener
est recommandée pour lire les listes
données, il peut arriver que l'association d'un ValueEventListener
à une liste
référence est utile.
Associer un ValueEventListener
à une liste de données renverra l'intégralité
liste de données sous la forme d'un DataSnapshot
unique, que vous pouvez ensuite lire en boucle sur
à des enfants individuels.
Même s'il n'y a qu'une seule correspondance pour la requête, l'instantané reste une liste. Il ne contient qu'un seul élément. Pour accéder à l'élément, vous devez le lire en boucle sur le résultat:
Kotlin+KTX
// My top posts by number of stars myTopPostsQuery.addValueEventListener(object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { for (postSnapshot in dataSnapshot.children) { // TODO: handle the post } } override fun onCancelled(databaseError: DatabaseError) { // Getting Post failed, log a message Log.w(TAG, "loadPost:onCancelled", databaseError.toException()) // ... } })
Java
// My top posts by number of stars myTopPostsQuery.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) { // TODO: handle the post } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { // Getting Post failed, log a message Log.w(TAG, "loadPost:onCancelled", databaseError.toException()); // ... } });
Ce modèle peut s'avérer utile lorsque vous souhaitez récupérer tous les enfants d'une liste en une seule opération, plutôt que d'écouter des événements onChildAdded
supplémentaires.
Dissocier les écouteurs
Les rappels sont supprimés en appelant la méthode removeEventListener()
sur votre
Documentation de référence sur la base de données Firebase
Si un écouteur a été ajouté plusieurs fois à un emplacement de données, il est appelé plusieurs fois pour chaque événement, et vous devez le dissocier fois pour le supprimer complètement.
L'appel de removeEventListener()
sur un écouteur parent n'entraîne pas
supprimer automatiquement les écouteurs enregistrés sur ses nœuds enfants ;
removeEventListener()
doit également être appelé sur tous les écouteurs enfants.
pour supprimer le rappel.
Trier et filtrer des données
Vous pouvez utiliser la classe Query
Realtime Database pour récupérer des données triées par clé, par valeur ou par valeur d'un enfant. Vous pouvez également filtrer
le résultat trié à un nombre spécifique
de résultats ou une plage de clés ou
valeurs.
Trier les données
Pour récupérer des données triées, commencez par spécifier l'une des méthodes de tri déterminent comment les résultats sont classés:
Méthode | Utilisation |
---|---|
orderByChild() |
Classez les résultats en fonction de la valeur d'une clé enfant spécifiée ou d'un chemin d'accès enfant imbriqué. |
orderByKey()
| Classez les résultats par clés enfants. |
orderByValue() |
Classez les résultats par valeurs enfants. |
Vous ne pouvez utiliser qu'une méthode de tri à la fois. Appeler une méthode de tri plusieurs fois dans la même requête génère une erreur.
L'exemple suivant montre comment récupérer la liste des données top des posts triés par nombre d'étoiles:
Kotlin+KTX
// My top posts by number of stars val myUserId = uid val myTopPostsQuery = databaseReference.child("user-posts").child(myUserId) .orderByChild("starCount") myTopPostsQuery.addChildEventListener(object : ChildEventListener { // TODO: implement the ChildEventListener methods as documented above // ... })
Java
// My top posts by number of stars String myUserId = getUid(); Query myTopPostsQuery = databaseReference.child("user-posts").child(myUserId) .orderByChild("starCount"); myTopPostsQuery.addChildEventListener(new ChildEventListener() { // TODO: implement the ChildEventListener methods as documented above // ... });
Ce code définit une requête qui, lorsqu'elle est combinée à un écouteur enfant, synchronise le client avec les messages de l'utilisateur à partir du chemin d'accès dans la base de données. en fonction de leur ID utilisateur, classés selon le nombre d'étoiles que chaque post a reçues. Cette technique d'utilisation d'ID comme clés d'index s'appelle la distribution ramifiée des données. plus en détail dans Structurez votre base de données.
L'appel de la méthode orderByChild()
spécifie la clé enfant pour ordonner les
. Dans ce cas, les messages sont triés en fonction de leur valeur
"starCount"
enfant. Les requêtes peuvent également être triées par ordre
enfants, au cas où vos données se présenteraient comme suit:
"posts": { "ts-functions": { "metrics": { "views" : 1200000, "likes" : 251000, "shares": 1200, }, "title" : "Why you should use TypeScript for writing Cloud Functions", "author": "Doug", }, "android-arch-3": { "metrics": { "views" : 900000, "likes" : 117000, "shares": 144, }, "title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)", "author": "Doug", } },
Dans cet exemple, nous pouvons classer les éléments de notre liste en fonction de valeurs imbriquées sous les
metrics
en spécifiant le chemin d'accès relatif vers l'enfant imbriqué dans notre
Appel orderByChild()
.
Kotlin+KTX
// Most viewed posts val myMostViewedPostsQuery = databaseReference.child("posts") .orderByChild("metrics/views") myMostViewedPostsQuery.addChildEventListener(object : ChildEventListener { // TODO: implement the ChildEventListener methods as documented above // ... })
Java
// Most viewed posts Query myMostViewedPostsQuery = databaseReference.child("posts") .orderByChild("metrics/views"); myMostViewedPostsQuery.addChildEventListener(new ChildEventListener() { // TODO: implement the ChildEventListener methods as documented above // ... });
Pour en savoir plus sur l'ordre des autres types de données, consultez la section Ordre des données de requête.
Filtrer les données
Pour filtrer les données, vous pouvez combiner n'importe quelle méthode de limite ou de plage avec une méthode ordre par lors de la création d'une requête.
Méthode | Utilisation |
---|---|
limitToFirst() |
Définit le nombre maximal d'éléments à renvoyer à partir du début de la variable une liste numérotée de résultats. |
limitToLast() |
Définit le nombre maximal d'articles à renvoyer à partir de la fin de la période liste de résultats. |
startAt() |
Afficher des éléments supérieurs ou égaux à la clé ou à la valeur spécifiée en fonction de la méthode de tri choisie choisie. |
startAfter() |
Afficher des éléments supérieurs à la clé ou à la valeur spécifiée en fonction de la méthode de tri choisie choisie. |
endAt() |
Éléments inférieurs ou égaux à la clé ou à la valeur spécifiée en fonction de la méthode de tri choisie choisie. |
endBefore() |
Renvoie les éléments inférieurs à la clé ou à la valeur spécifiée, en fonction de la méthode de tri choisie. |
equalTo() |
Renvoyer des éléments égaux à la clé ou à la valeur spécifiée en fonction de la méthode de tri choisie choisie. |
Contrairement aux méthodes de tri, vous pouvez combiner plusieurs fonctions de limite ou de plage.
Par exemple, vous pouvez combiner les méthodes startAt()
et endAt()
pour limiter
les résultats à une plage de valeurs spécifiée.
Même s'il n'y a qu'une seule correspondance pour la requête, l'instantané est toujours une liste ; elle ne contient qu'un seul élément. Pour accéder à l'élément, vous devez : pour effectuer une boucle sur le résultat:
Kotlin+KTX
// My top posts by number of stars myTopPostsQuery.addValueEventListener(object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { for (postSnapshot in dataSnapshot.children) { // TODO: handle the post } } override fun onCancelled(databaseError: DatabaseError) { // Getting Post failed, log a message Log.w(TAG, "loadPost:onCancelled", databaseError.toException()) // ... } })
Java
// My top posts by number of stars myTopPostsQuery.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) { // TODO: handle the post } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { // Getting Post failed, log a message Log.w(TAG, "loadPost:onCancelled", databaseError.toException()); // ... } });
Limiter le nombre de résultats
Vous pouvez utiliser les méthodes limitToFirst()
et limitToLast()
pour définir un
nombre maximal d'enfants à synchroniser pour un rappel donné. Par exemple, si
si vous utilisez limitToFirst()
pour définir une limite de 100, vous ne recevez initialement que jusqu'à
à 100 rappels onChildAdded()
. Si vous avez moins de 100 éléments stockés dans votre
base de données Firebase, un rappel onChildAdded()
se déclenche pour chaque élément.
À mesure que les éléments changent, vous recevez des rappels onChildAdded()
pour les éléments qui saisissent la valeur
une requête et des rappels onChildRemoved()
pour les éléments qui s'en abandonnent
le nombre total reste à 100.
L'exemple suivant montre comment une application de blog définit une requête pour récupérer la liste des 100 posts les plus récents de tous les utilisateurs:
Kotlin+KTX
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys. databaseReference.child("posts").limitToFirst(100)
Java
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys Query recentPostsQuery = databaseReference.child("posts") .limitToFirst(100);
Cet exemple définit uniquement une requête, afin de synchroniser les données dont elle a besoin être associés à un écouteur.
Filtrer par clé ou valeur
Vous pouvez utiliser startAt()
, startAfter()
, endAt()
, endBefore()
et
equalTo()
pour choisir des points de départ, d'arrivée et d'équivalence arbitraires pour
requêtes. Cela peut être utile pour la pagination des données ou la recherche d'éléments avec des enfants
qui ont une valeur spécifique.
Comment les données de requête sont-elles ordonnées ?
Cette section explique comment les données sont triées par chacune des méthodes de tri de la classe Query
.
orderByChild
Lorsque vous utilisez orderByChild()
, les données contenant la clé enfant spécifiée sont
dans l'ordre suivant:
- Les enfants dont la valeur de la clé enfant spécifiée est
null
sont affichés en premier. - Enfants dont la valeur est
false
pour la clé enfant spécifiée viennent ensuite. Si plusieurs enfants ont la valeurfalse
, ils sont triées de manière lexicographique par clé. - Enfants dont la valeur est
true
pour la clé enfant spécifiée viennent ensuite. Si plusieurs enfants ont la valeurtrue
, ils sont triées de manière lexicographique par clé. - Les enfants avec une valeur numérique arrivent ensuite, triés par ordre croissant. Si plusieurs enfants ont la même valeur numérique pour l'enfant spécifié les nœuds sont triés par clé.
- Les chaînes apparaissent après les nombres et sont triées de manière lexicographique par ordre croissant commande. Si plusieurs enfants ont la même valeur pour l'enfant spécifié ils sont triés de façon lexicographique par clé.
- Les objets apparaissent en dernier et sont triés de façon lexicographique par clé, dans l'ordre croissant.
orderByKey
Lorsque vous utilisez orderByKey()
pour trier vos données, elles sont renvoyées dans l'ordre croissant
par clé.
- Les enfants avec une clé pouvant être analysée en tant qu'entier 32 bits sont placés en premier, triés par ordre croissant.
- Les enfants avec une valeur de chaîne comme clé arrivent ensuite, triés de manière lexicographique par ordre croissant.
orderByValue
Lorsque vous utilisez orderByValue()
, les enfants sont triés en fonction de leur valeur. Les critères de tri sont les mêmes que dans orderByChild()
, sauf que la valeur du nœud est utilisée à la place de la valeur d'une clé enfant spécifiée.