Recherche…


Remarques

Autres sujets connexes:

Gestionnaire d'événements Firebase Realtime DataBase

Première initialisation de la base de données Firebase:

FirebaseDatabase database = FirebaseDatabase.getInstance();

Écrivez dans votre base de données:

// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");

myRef.setValue("Hello, World!");

Lire depuis votre base de données:

// Read from the database
myRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        // This method is called once with the initial value and again
        // whenever data at this location is updated.
        String value = dataSnapshot.getValue(String.class);
        Log.d(TAG, "Value is: " + value);
    }

    @Override
    public void onCancelled(DatabaseError error) {
        // Failed to read value
        Log.w(TAG, "Failed to read value.", error.toException());
    }
});

Récupérer des données sur des événements Android:

ChildEventListener childEventListener = new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
        Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
        Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());
    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {
        Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());

    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
        Log.d(TAG, "onChildMoved:" + 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();
    }
};
ref.addChildEventListener(childEventListener);

Installation rapide

  1. Complétez la partie Installation et configuration pour connecter votre application à Firebase.
    Cela créera le projet dans Firebase.

  2. Ajoutez la dépendance pour la base de données Firebase Realtime à votre fichier build.gradle niveau du build.gradle :

compile 'com.google.firebase:firebase-database:10.2.1'
  1. Configurer les règles de base de données Firebase

Vous êtes maintenant prêt à travailler avec la base de données Realtime sous Android.

Par exemple, vous écrivez un message Hello World dans la base de données sous la clé de message .

// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");

myRef.setValue("Hello, World!");

Concevoir et comprendre comment récupérer des données en temps réel à partir de la base de données Firebase

Cet exemple suppose que vous avez déjà configuré une base de données Firebase Realtime. Si vous êtes un démarreur, alors s'il vous plaît informez-vous ici sur la façon d'ajouter Firebase à votre projet Android.

Tout d'abord, ajoutez la dépendance de la base de données Firebase au fichier build.gradle au niveau de l'application:

compile 'com.google.firebase:firebase-database:9.4.0'

Maintenant, laissez-nous créer une application de chat qui stocke les données dans la base de données Firebase.

Étape 1: Créer une classe nommée Chat

Il suffit de créer une classe avec certaines variables de base requises pour le chat:

public class Chat{
    public String name, message;
}

Étape 2: créer des données JSON

Pour envoyer / récupérer des données vers / depuis la base de données Firebase, vous devez utiliser JSON. Supposons que certaines discussions sont déjà stockées au niveau racine dans la base de données. Les données de ces chats peuvent ressembler à ceci:

[
    {
        "name":"John Doe",
        "message":"My first Message"
    },
    {
        "name":"John Doe",
        "message":"Second Message"
    },
    {
        "name":"John Doe",
        "message":"Third Message"
    }
]

Étape 3: Ajouter les auditeurs

Il existe trois types d'auditeurs. Dans l'exemple suivant, nous allons utiliser le childEventListener :

DatabaseReference chatDb = FirebaseDatabase.getInstance().getReference() // Referencing the root of the database.
        .child("chats"); // Referencing the "chats" node under the root.

chatDb.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
        // This function is called for every child id chat in this case, so using the above
        // example, this function is going to be called 3 times.
        
        // Retrieving the Chat object from this function is simple.
        Chat chat; // Create a null chat object.

        // Use the getValue function in the dataSnapshot and pass the object's class name to
        // which you want to convert and get data. In this case it is Chat.class.
        chat = dataSnapshot.getValue(Chat.class);

        // Now you can use this chat object and add it into an ArrayList or something like
        // that and show it in the recycler view.
    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String s) {
        // This function is called when any of the node value is changed, dataSnapshot will
        // get the data with the key of the child, so you can swap the new value with the
        // old one in the ArrayList or something like that.

        // To get the key, use the .getKey() function.
        // To get the value, use code similar to the above one.
    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {
        // This function is called when any of the child node is removed. dataSnapshot will
        // get the data with the key of the child.

        // To get the key, use the s String parameter .
    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String s) {
        // This function is called when any of the child nodes is moved to a different position.

        // To get the key, use the s String parameter.
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        // If anything goes wrong, this function is going to be called.

        // You can get the exception by using databaseError.toException();
    }
});

Étape 4: Ajouter des données à la base de données

Créez simplement un objet de classe Chat et ajoutez les valeurs comme suit:

Chat chat=new Chat();
chat.name="John Doe";
chat.message="First message from android";

Maintenant, obtenez une référence au nœud de chats comme lors de la session de récupération:

DatabaseReference chatDb = FirebaseDatabase.getInstance().getReference().child("chats");

Avant de commencer à ajouter des données, gardez à l'esprit que vous avez besoin d'une référence de plus, car un nœud de discussion a plusieurs autres nœuds et l'ajout d'un nouveau chat implique l'ajout d'un nouveau nœud contenant les détails de la discussion. Nous pouvons générer un nom nouveau et unique du noeud à l'aide de la fonction push() sur l'objet DatabaseReference , qui renverra une autre DatabaseReference , qui à son tour pointe sur un noeud nouvellement formé pour insérer les données de discussion.

Exemple

// The parameter is the chat object that was newly created a few lines above.
chatDb.push().setValue(chat);

La fonction setValue() s'assurera que toutes les fonctions onDataChanged de l'application sont appelées (y compris le même périphérique), qui se trouve être l'écouteur attaché du nœud "chats".

Dénormalisation: Structure de base de données plate

La dénormalisation et une structure de base de données plate sont nécessaires pour télécharger efficacement des appels séparés. Avec la structure suivante, il est également possible de maintenir des relations bidirectionnelles. L'inconvénient de cette approche est que vous devez toujours mettre à jour les données à plusieurs endroits.

Par exemple, imaginez une application qui permet à l'utilisateur de stocker des messages pour lui-même (mémos).

Structure de base de données à plat souhaitée:

|--database
  |-- memos
     |-- memokey1
       |-- title: "Title"
       |-- content: "Message"
     |-- memokey2
       |-- title: "Important Title"
       |-- content: "Important Message"
  |-- users
     |-- userKey1
       |-- name: "John Doe"
       |-- memos
         |-- memokey1 : true //The values here don't matter, we only need the keys.
         |-- memokey2 : true
     |-- userKey2
       |-- name: "Max Doe"

La classe de mémo utilisée

public class Memo {
    private String title, content;
    //getters and setters ... 

    //toMap() is necessary for the push process
    private Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put("title", title);
        result.put("content", content);
        return result;
    }
}

Récupérer les mémos d'un utilisateur

//We need to store the keys and the memos seperately
private ArrayList<String> mKeys = new ArrayList<>();
private ArrayList<Memo> mMemos = new ArrayList<>();

//The user needs to be logged in to retrieve the uid
String currentUserId = FirebaseAuth.getInstance().getCurrentUser().getUid();

//This is the reference to the list of memos a user has 
DatabaseReference currentUserMemoReference = FirebaseDatabase.getInstance().getReference()
    .child("users").child(currentUserId).child("memos");

//This is a reference to the list of all memos
DatabaseReference memoReference = FirebaseDatabase.getInstance().getReference()
    .child("memos");

//We start to listen to the users memos, 
//this will also retrieve the memos initially
currentUserMemoReference.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            //Here we retrieve the key of the memo the user has.
            String key = dataSnapshot.getKey(); //for example memokey1
            //For later manipulations of the lists, we need to store the key in a list
            mKeys.add(key);
            //Now that we know which message belongs to the user, 
            //we request it from our memos:
            memoReference.child(key).addValueEventListener(new ValueEventListener() {
                @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                         //Here we retrieve our memo:
                         Memo memo = dataSnapshot.getValue(Memo.class);
                         mMemos.add(memo);
                    }

                @Override
                public void onCancelled(DatabaseError databaseError) { }
            });                           
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) { }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) { }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) { }

        @Override
        public void onCancelled(DatabaseError databaseError) { }
    }

Créer un mémo

//The user needs to be logged in to retrieve the uid
String currentUserUid = FirebaseAuth.getInstance().getCurrentUser().getUid();

//This is the path to the list of memos a user has 
String userMemoPath = "users/" + currentUserUid + "/memos/";

//This is the path to the list of all memos
String memoPath = "memos/";

//We need to retrieve an unused key from the memos reference
DatabaseReference memoReference = FirebaseDatabase.getInstance().getReference().child("memos");
String key = memoReference.push().getKey();
Memo newMemo = new Memo("Important numbers", "1337, 42, 3.14159265359");

Map<String, Object> childUpdates = new HashMap<>(); 
//The second parameter **here** (the value) does not matter, it's just that the key exists
childUpdates.put(userMemoPath + key, true);
childUpdates.put(memoPath + key, newMemo.toMap());

FirebaseDatabase.getInstance().getReference().updateChildren(childUpdates);

Après le push ou la base de données ressemble à ceci:

|--database
  |-- memos
     |-- memokey1
       |-- title: "Title"
       |-- content: "Message"
     |-- memokey2
       |-- title: "Important Title"
       |-- content: "Important Message"
     |-- generatedMemokey3 
       |-- title: "Important numbers"
       |-- content: "1337, 42, 3.14159265359"
  |-- users
     |-- userKey1
       |-- name: "John Doe"
       |-- memos
         |-- memokey1 : true //The values here don't matter, we only need the keys.
         |-- memokey2 : true
         |-- generatedMemokey3 : true
     |-- userKey2
       |-- name: "Max Doe"

Comprendre la base de données JSON Firebase

Avant de nous salir le code, j'estime qu'il est nécessaire de comprendre comment les données sont stockées dans Firebase. Contrairement aux bases de données relationnelles, Firebase stocke les données au format JSON. Considérez chaque ligne d'une base de données relationnelle comme un objet JSON (qui est essentiellement une paire clé-valeur non ordonnée). Ainsi, le nom de la colonne devient clé et la valeur stockée dans cette colonne pour une ligne particulière est la valeur. De cette manière, la ligne entière est représentée comme un objet JSON et une liste de ceux-ci représente une table de base de données entière. L'avantage immédiat que je vois pour cette modification du schéma devient une opération beaucoup moins chère par rapport aux anciens SGBDR. Il est plus facile d'ajouter quelques attributs supplémentaires à un JSON que de modifier une structure de table.

Voici un exemple de JSON pour montrer comment les données sont stockées dans la base de données:

   {
    "user_base" : {
      "342343" : {
        "email" : "[email protected]",
        "authToken" : "some string",
        "name" : "Kaushal",
        "phone" : "+919916xxxxxx",
        "serviceProviderId" : "firebase",
        "signInServiceType" : "google",
      },
      "354895" : {
        "email" : "[email protected]",
        "authToken" : "some string",
        "name" : "devil",
        "phone" : "+919685xxxxxx",
        "serviceProviderId" : "firebase",
        "signInServiceType" : "github"
      },
      "371298" : {
        "email" : "[email protected]",
        "authToken" : "I am batman",
        "name" : "Bruce Wayne",
        "phone" : "+14085xxxxxx",
        "serviceProviderId" : "firebase",
        "signInServiceType" : "shield"
      }
    },
    "user_prefs": {
      "key1":{
        "data": "for key one"
      },
      "key2":{
        "data": "for key two"
      },
      "key3":{
        "data": "for key three"
      }
    },
    //other structures
  }

Cela montre clairement comment les données que nous stockions dans des bases de données relationnelles peuvent être stockées au format JSON. Ensuite, voyons comment lire ces données sur les appareils Android.

Récupération de données à partir de Firebase

Je suppose que vous savez déjà comment ajouter des dépendances progressives à la base de feu dans le studio Android. Si vous ne suivez pas simplement le guide d' ici . Ajoutez votre application dans la console firebase, synchronisez votre studio Android après avoir ajouté des dépendances. Toutes les dépendances ne sont pas nécessaires, mais uniquement la base de données firebase et l'authentification firebase.

Maintenant que nous savons comment les données sont stockées et comment ajouter des dépendances progressives, voyons comment utiliser le SDK Android Firebase importé pour récupérer des données.

créer une référence de base de données firebase

DatabaseReference userDBRef = FirebaseDatabase.getInstance().getReference();
// above statement point to base tree
userDBRef = DatabaseReference.getInstance().getReference().child("user_base")
// points to user_base table JSON (see previous section)

à partir de là, vous pouvez chaîner plusieurs appels de méthode child () pour pointer vers les données qui vous intéressent. Par exemple, si des données sont stockées comme décrit dans la section précédente et que vous souhaitez indiquer l'utilisateur Bruce Wayne, vous pouvez utiliser:

DatabaseReference bruceWayneRef = userDBRef.child("371298");
// 371298 is key of bruce wayne user in JSON structure (previous section)

Ou passez simplement la référence entière à l'objet JSON:

DatabaseReference bruceWayneRef = DatabaseReference.getInstance().getReference()
     .child("user_base/371298");
// deeply nested data can also be referenced this way, just put the fully
// qualified path in pattern shown in above code "blah/blah1/blah1-2/blah1-2-3..."

Maintenant que nous avons la référence des données que nous voulons récupérer, nous pouvons utiliser des écouteurs pour récupérer des données dans des applications Android. Contrairement aux appels traditionnels où vous lancez des appels d'API REST en utilisant retrofit ou volley, un simple écouteur de rappel est nécessaire pour obtenir les données. Firebase sdk appelle les méthodes de rappel et vous avez terminé.

Il existe essentiellement deux types d'écouteurs que vous pouvez attacher, l'un est ValueEventListener et l'autre est ChildEventListener (décrit dans la section suivante). Pour tout changement de données sous le nœud auquel nous avons des références et des écouteurs ajoutés, les écouteurs d'événement de valeur renvoient la structure JSON complète et l'écouteur d'événement enfant retourne un enfant spécifique où la modification s'est produite. Les deux sont utiles à leur manière. Pour extraire les données de Firebase, nous pouvons ajouter un ou plusieurs écouteurs à une référence de base de données firebase (listez userDBRef que nous avons créé précédemment).

Voici un exemple de code (code explicatif après code):

userDBRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        User bruceWayne = dataSnapshot.child("371298").getValue(User.class);
        // Do something with the retrieved data or Bruce Wayne
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.e("UserListActivity", "Error occured");
        // Do something about the error
    });

Avez-vous remarqué le type de classe passé? DataSnapshot peut convertir les données JSON dans nos POJO définis, en utilisant simplement le bon type de classe.

Si votre cas d'utilisation ne nécessite pas l'intégralité des données (dans notre cas la table user_base) chaque fois qu'un petit changement survient ou que vous souhaitez récupérer les données une seule fois , vous pouvez utiliser la méthode addListenerForSingleValueEvent () de la référence de base de données. Cela déclenche le rappel une seule fois.

userDBRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        // Do something
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        // Do something about the error
    });

Les exemples ci-dessus vous donneront la valeur du noeud JSON. Pour obtenir la clé, appelez simplement:

String myKey = dataSnapshot.getKey();

Écoute des mises à jour d'enfants

Prenez un cas d'utilisation, comme une application de chat ou une application de liste d'épicerie collaborative (qui nécessite essentiellement une liste d'objets à synchroniser entre les utilisateurs). Si vous utilisez une base de données firebase et ajoutez un écouteur d'événement de valeur au nœud parent ou au nœud parent de liste d'épicerie, vous finirez avec toute la structure de discussion depuis le début du chat (chaque fois qu'un nœud de discussion est ajouté). c.-à-d. que quelqu'un dit bonjour). Que nous ne voulons pas faire, ce qui nous intéresse, c'est seulement le nouveau nœud ou seulement l'ancien nœud qui a été supprimé ou modifié, les autres ne doivent pas être retournés.

Dans ce cas, nous pouvons utiliser ChildEvenListener . Sans plus tarder, voici un exemple de code (voir sections prev pour un exemple de données JSON):

userDBRef.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String s) {
    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {
    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String s) {
        //If not dealing with ordered data forget about this
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
    });

Les noms de méthode sont explicites. Comme vous pouvez le voir à chaque fois qu'un nouvel utilisateur est ajouté ou qu'une propriété d'un utilisateur existant est modifiée ou qu'un utilisateur est supprimé ou supprimé, la méthode de rappel appropriée est appelée avec les données pertinentes. Donc, si vous conservez l'interface utilisateur actualisée, par exemple pour une application de chat, obtenez le fichier JSON de l'analyse onChildAdded () dans POJO et placez-le dans votre interface utilisateur. Rappelez-vous juste de supprimer votre auditeur lorsque l'utilisateur quitte l'écran.

onChildChanged () donne la valeur enfant entière avec les propriétés modifiées (nouvelles).

onChiledRemoved () renvoie le nœud enfant supprimé.

Récupération de données avec pagination

Lorsque vous avez une énorme base de données JSON, l'ajout d'un écouteur d'événement de valeur n'a pas de sens. Il retournera l'énorme JSON et l'analyse prendra beaucoup de temps. Dans de tels cas, nous pouvons utiliser la pagination et récupérer une partie des données et les afficher ou les traiter. Un peu comme le chargement paresseux ou comme chercher d'anciennes discussions lorsque l'utilisateur clique sur un ancien chat. Dans ce cas, Query peut être utilisé.

Prenons notre ancien exemple dans les sections précédentes. La base d'utilisateurs contient 3 utilisateurs, si le nombre d'utilisateurs est supérieur à trois cent mille et que vous souhaitez récupérer la liste d'utilisateurs par lots de 50:

// class level
final int limit = 50;
int start = 0;

// event level
Query userListQuery = userDBRef.orderByChild("email").limitToFirst(limit)
        .startAt(start)
userListQuery.addValueEventListener(new ValueEventListener() {
    @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
        // Do something
        start += (limit+1);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        // Do something about the error
    });

Ici, la valeur ou les événements enfants peuvent être ajoutés et écoutés. Appelez à nouveau la requête pour récupérer les 50 suivants. Assurez-vous d'ajouter la méthode orderByChild () , cela ne fonctionnera pas sans cela. Firebase doit connaître l'ordre dans lequel vous paginez.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow