La base de données en temps réel de Firebase
Sommaire
- 1- Objectif
- 2- Présentation
- 3- Les principales capacités de la base de données en temps réel de firebase
- 4- Configuration et installation de bases de données en temps réel
- 4.1- Configuration du projet Firebase
- 4.2- Génération d'un fichier de configuration de projet Firebase:
- 4.3- Installation de votre fichier de configuration Firebase :
- 4.4- Ajout de dépendances Firebase :
- 4.5- Initialisation de la base de données en temps réel Firebase :
- 5- Écriture dans la base de données en temps réel de Firebase
- 5.1- Initialisation de la base de données
- 5.1.1- Initialisation de Firebase
- 5.1.2- Créer une référence à la base de données
- 5.2- Écriture dans la base de données
- 5.2.1- Écrire une simple valeur
- 5.2.2- Écrire un objet (map)
- 5.2.3- Ajouter un nouvel élément avec une clé générée automatiquement (push)
- 6- Lecture dans la base de données en temps réel de Firebase
- 6.1- Initialisation de la base de données
- 6.1.1- Initialisation de Firebase
- 6.1.2- Créer une référence à la base de données
- 6.2- Lecture dans la base de données
- 6.2.1- Lire une seule fois (get)
- 6.2.2- Écouter en temps réel (onValue)
- 6.2.3- Lire une liste de données
- 7- Modification d’une information dans Firebase Realtime Database
- 7.1- Modifier une valeur existante
- 7.1.1- Modifier une valeur simple
- 7.1.2- Modifier un seul champ dans un objet
- 7.1.3- Modifier plusieurs champs en même temps
- 7.1.4- Modifier un élément dont la clé est générée automatiquement
- 8- Suppression d’une information dans Firebase Realtime Database
- 8.1- Supprimer une donnée existante
- 8.1.1- Supprimer une valeur simple
- 8.1.2- Supprimer un utilisateur avec son ID
- 8.1.3- Supprimer un élément à clé générée automatiquement
- 8.1.4- Supprimer un seul champ dans un objet
- 9- Exemple Flutter complet : CRUD avec Firebase Realtime Database
- 9.1- 1. Ajouter les dépendances dans
pubspec.yaml
- 9.2- 2. Initialiser Firebase dans
main.dart
- 9.3- 3. Créer la page firebaseService
firebase_service.dart
- 9.4- 4. Créer la page principale
home_page.dart
- 9.4.1- Cours Flutter
La base de données en temps réel de Firebase
-
Objectif
- Firebase Real-time Database
-
Présentation
- La base de données temps réel Firebase est une base de données hébergée dans le cloud, stockant les données au format JSON. Les données sont synchronisées en temps réel avec chaque client connecté. Tous nos clients partagent une instance de base de données temps réel et reçoivent automatiquement les mises à jour avec les données les plus récentes lorsque nous développons des applications multiplateformes avec nos SDK iOS et JavaScript.
- La base de données Firebase Realtime est une base de données NoSQL permettant de stocker et de synchroniser les données entre nos utilisateurs en temps réel.
- Il s’agit d’un objet JSON volumineux que les développeurs peuvent gérer en temps réel. Grâce à une API unique, la base de données Firebase fournit à l’application la valeur actuelle des données et leurs mises à jour. La synchronisation en temps réel permet à nos utilisateurs d’accéder facilement à leurs données depuis n’importe quel appareil, web ou mobile.
- La base de données en temps réel facilite la collaboration entre nos utilisateurs. Elle est fournie avec des SDK mobiles et web, qui nous permettent de développer notre application sans serveur. Lorsque nos utilisateurs sont hors ligne, les SDK de la base de données en temps réel utilisent le cache local de l’appareil pour traiter et stocker les modifications. Les données locales sont automatiquement synchronisées dès la connexion de l’appareil.
-
Les principales capacités de la base de données en temps réel de firebase
- Une base de données en temps réel est capable de fournir tous les services, en ligne et hors ligne. Ces fonctionnalités incluent l’accessibilité depuis l’appareil client, la mise à l’échelle sur plusieurs bases de données, et bien plus encore.
- En temps réel
- La base de données en temps réel Firebase utilise la synchronisation des données plutôt que les requêtes HTTP. Tout appareil connecté reçoit les mises à jour en quelques millisecondes. Elle ne prend pas en compte le code réseau et offre des expériences collaboratives et immersives.
- Hors ligne
- Le SDK de base de données Firebase conserve nos données sur le disque, ce qui permet aux applications Firebase de rester réactives même hors ligne. L’appareil client reçoit les modifications manquantes une fois la connexion rétablie.
- Accessible depuis les appareils clients
- Aucun serveur d’application n’est nécessaire pour accéder à la base de données Firebase Real-Time. Nous pouvons y accéder directement depuis un appareil mobile ou un navigateur web. La validation et la sécurité des données sont assurées par les règles de sécurité Firebase Real-Time Database, des règles basées sur des expressions exécutées lors de la lecture ou de l’écriture des données.
- Mise à l’échelle sur plusieurs bases de données
- Grâce à l’offre Firebase Real-Time Database sur Blaze, nous pouvons répondre aux besoins en données de notre application en répartissant nos données sur plusieurs instances de base de données au sein d’un même projet Firebase.
- L’authentification est simplifiée grâce à Firebase Authentication sur notre projet et les utilisateurs de nos instances de base de données sont authentifiés.
- L’accès aux données de chaque base de données est contrôlé grâce à des règles Firebase Real-Time personnalisées, disponibles pour chaque instance.
-
Configuration et installation de bases de données en temps réel
-
Configuration du projet Firebase
- Accédez à la console Firebase et créez un nouveau projet.
- Avant de pouvoir utiliser l’un des services cloud de Google, vous devez configurer un projet sur la console Firebase . Ensuite, vous pouvez créer votre base de données en temps réel et la gérer directement depuis la console.
- Accédez à console.firebase.google.com et connectez-vous à l’aide de votre compte Gmail.
- Cliquez sur le bouton « créer un projet » puis sur le bouton continuer.
- Cliquez sur « Ajouter Firebase à votre application Flutter » et suivez les instructions d’installation. Vous obtiendrez ainsi un fichier
google-services.json
à placer dans le répertoireandroid/app de votre projet Flutter. -
Génération d’un fichier de configuration de projet Firebase:
- Sur la console Firebase , ajoutez une nouvelle application Android ou sélectionnez une application Android existante pour votre projet Firebase.
- Le «
Nom du package Android
» doit correspondre au nom du package de votre projet local, créé au démarrage du projet Flutter. - Le nom du package actuel se trouve dans votre fichier Gradle de module (au niveau de l’application), généralement
android/app/build.gradle
dans la sectiondefaultConfig
(exemple de nom de package : com.yourcompany.yourproject). - Une fois votre application Android enregistrée, téléchargez le fichier de configuration depuis la console Firebase (fichier nommé
google-services.json
). Ajoutez ce fichier au répertoire de android/app votre projet Flutter. -
Installation de votre fichier de configuration Firebase :
- Pour permettre à Firebase d’utiliser la configuration sur Android, le plugin « google-services » doit être appliqué au projet. Cela nécessite la modification de deux fichiers du android/répertoire.
- Tout d’abord, ajoutez le plugin «
google-services
» en tant que dépendance à l’intérieur du fichier :android/build.gradle
buildscript { dependencies { // ... other dependencies classpath 'com.google.gms:google-services:4.3.8' } }
- Enfin, exécutez le plugin en ajoutant ce qui suit sous la ligne apply plugin: ‘
com.android.application
‘, dans le fichier :/android/app/build.gradle
buildscript { apply plugin: 'com.google.gms.google-services'
- Si ton projet utilisait Gradle Kotlin DSL, les fichiers seraient en .gradle.kts (extension .kts pour Kotlin Script), et la syntaxe serait différente, par exemple :
-
Ajout de dépendances Firebase :
- Ouvrez votre projet Flutter et accédez au fichier
pubspec.yaml
. - Ajoutez les dépendances suivantes sous la dependenciessection :
- Exécutez flutter pub getpour récupérer les dépendances nouvellement ajoutées.
-
Initialisation de la base de données en temps réel Firebase :
- Ouvrez le fichier
main.dart
dans votre projet Flutter. - Importez les packages Firebase et Flutter nécessaires :
-
Écriture dans la base de données en temps réel de Firebase
-
Initialisation de la base de données
- Pour écrire dans Firebase Realtime Database, nous devons d’abord obtenir une instance de la base de données, puis référencer l’emplacement où nous voulons écrire.
-
Initialisation de Firebase
- Dans lib/main.dart :
-
Créer une référence à la base de données
-
Écriture dans la base de données
-
Écrire une simple valeur
-
Écrire un objet (map)
-
Ajouter un nouvel élément avec une clé générée automatiquement (push)
-
Lecture dans la base de données en temps réel de Firebase
-
Initialisation de la base de données
- Pour lire depuis Firebase Realtime Database, nous devons d’abord obtenir une instance de la base de données, puis référencer l’emplacement que nous souhaitons écouter.
-
Initialisation de Firebase
- Dans lib/main.dart :
-
Créer une référence à la base de données
-
Lecture dans la base de données
-
Lire une seule fois (get)
-
Écouter en temps réel (onValue)
-
Lire une liste de données
-
Modification d’une information dans Firebase Realtime Database
-
Modifier une valeur existante
- Pour modifier une valeur dans Firebase Realtime Database, on utilise généralement la méthode
update()
ouset()
sur un nœud existant. -
Modifier une valeur simple
set()
remplace entièrement la valeur du nœud, même si elle existait avant.-
Modifier un seul champ dans un objet
update()
permet de modifier un ou plusieurs champs **sans écraser tout l’objet**.-
Modifier plusieurs champs en même temps
-
Modifier un élément dont la clé est générée automatiquement
- Dans ce cas, tu dois connaître la clé générée (par exemple, en la stockant lors du push ou en la récupérant avec un
get()
). -
Suppression d’une information dans Firebase Realtime Database
-
Supprimer une donnée existante
- Pour supprimer une donnée, on utilise la méthode
remove()
sur la référence du nœud concerné. -
Supprimer une valeur simple
- Cette méthode supprime entièrement le nœud
message
de la base. -
Supprimer un utilisateur avec son ID
- Ici, l’utilisateur avec l’ID
userId123
sera supprimé de la base. -
Supprimer un élément à clé générée automatiquement
- Tu dois connaître la clé générée automatiquement (par exemple :
cléAuto123
). -
Supprimer un seul champ dans un objet
- Pour cela, on met la valeur à
null
avecupdate()
. -
Exemple Flutter complet : CRUD avec Firebase Realtime Database
-
1. Ajouter les dépendances dans
pubspec.yaml
-
2. Initialiser Firebase dans
main.dart
-
3. Créer la page firebaseService
firebase_service.dart
-
4. Créer la page principale
home_page.dart
plugins {
id("com.google.gms.google-services")
}
Donc :
En Groovy ➔ tu faisapply plugin: '...'
En Kotlin DSL ➔ tu faisplugins { id("...") }
dépendances :
flutter :
sdk : flutter
firebase_core : ^1.4.0
firebase_database : ^11.0.0
// Importation des bibliothèques nécessaires
// Fournit les outils pour construire l'interface utilisateur Flutter
import 'package:flutter/material.dart';
// Permet l'initialisation de Firebase dans l'application
import 'package:firebase_core/firebase_core.dart';
// Permet d'interagir avec la base de données Realtime de Firebase
import 'package:firebase_database/firebase_database.dart';
// Fonction principale de l'application, point d'entrée du programme
void main() async {
// S'assure que le moteur Flutter est prêt avant toute opération asynchrone
WidgetsFlutterBinding.ensureInitialized();
// Initialise Firebase avec les paramètres par défaut (configuration définie dans firebase_options ou google-services.json)
await Firebase.initializeApp();
// Lance l'application Flutter en affichant le widget MyApp
runApp(MyApp());
}
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized(); // Nécessaire pour l'initialisation
await Firebase.initializeApp(); // Initialise Firebase
runApp(MyApp());
}
// Référence à la racine de la base de données
final DatabaseReference _database = FirebaseDatabase.instance.ref();
// Référence à un nœud spécifique (ex: "messages")
final DatabaseReference _messageRef = _database.child('messages');
import 'package:firebase_database/firebase_database.dart';
final database = FirebaseDatabase.instance.reference();
// Exemple d'écriture
void writeSimpleValue() {
database.child('message').set('Bonjour le monde!');
}
set() sert à écrire une valeur (écrase si quelque chose existe déjà).
void writeObject() {
Map utilisateur = {
'nomUtilisateur': 'Jean',
'email': 'jean@example.com',
};
database.child('utilisateurs').child('userId123').set(utilisateur);
}
void pushNewObject() {
Map utilisateur = {
'nomUtilisateur': 'Sami',
'email': 'sami@example.com',
};
database.child('utilisateurs').push().set(utilisateur);
}
push() crée une clé unique automatiquement.
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'home_page.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Firebase Realtime Example',
theme: ThemeData(primarySwatch: Colors.blue),
home: HomePage(),
);
}
}
// Référence à la racine de la base de données
final DatabaseReference _database = FirebaseDatabase.instance.ref();
// Référence à un nœud spécifique (ex: "messages")
final DatabaseReference _messageRef = _database.child('messages');
import 'package:firebase_database/firebase_database.dart';
final database = FirebaseDatabase.instance.ref();
// Exemple de lecture unique
void readOnce() async {
final snapshot = await database.child('message').get();
if (snapshot.exists) {
print('Valeur : ${snapshot.value}');
} else {
print('Pas de données disponibles.');
}
}
// get() lit une seule fois la donnée au chemin donné.
void listenToChanges() {
database.child('message').onValue.listen((DatabaseEvent event) {
final data = event.snapshot.value; print('Nouveau message: $data');
});
} // onValue écoute toutes les modifications de la donnée en temps réel.
void readList() async {
final snapshot = await database.child('utilisateurs').get(); if (snapshot.exists) { Map utilisateurs = snapshot.value as Map; utilisateurs.forEach((key, value) { print('Utilisateur $key: ${value['nomUtilisateur']}, ${value['email']}'); }); } } // Lecture d'une collection complète sous forme de Map.
void updateSimpleValue() { database.child('message').set('Bonjour modifié !'); }
void updateUserEmail() {
database.child('utilisateurs').child('userId123').update({
'email': 'nouveauemail@example.com',
});
}
void updateUserData() {
database.child('utilisateurs').child('userId123').update({
'nomUtilisateur': 'Jean Modifié',
'email': 'jeanmodifie@example.com',
});
}
// Supposons que la clé est "cléAuto123"
void updateAutoKeyUser() {
database.child('utilisateurs').child('cléAuto123').update({
'nomUtilisateur': 'Sami Modifié',
});
}
void deleteSimpleValue() {
database.child('message').remove();
}
void deleteUserById() {
database.child('utilisateurs').child('userId123').remove();
}
void deleteAutoKeyUser() {
database.child('utilisateurs').child('cléAuto123').remove();
}
void deleteUserField() {
database.child('utilisateurs').child('userId123').update({
'email': null, // Seul le champ "email" sera supprimé
});
}
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
firebase_core: ^3.13.0
firebase_database: ^11.3.5
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart'; // Pour initialiser Firebase
import 'home_page.dart'; // Importation de la page d'accueil
void main() async {
// S'assurer que Firebase est initialisé avant de lancer l'application
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(); // Initialisation de Firebase
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Firebase Realtime Example',
theme: ThemeData(primarySwatch: Colors.blue),
home: HomePage(), // Page affichée au lancement de l'application
);
}
}
// firebase_service.dart
import 'package:firebase_database/firebase_database.dart';
class FirebaseService {
final DatabaseReference _dbRef = FirebaseDatabase.instance.ref().child('messages');
DatabaseReference get ref => _dbRef;
Future<void> writeMessage(String message) async {
await _dbRef.push().set({'text': message});
}
Future<void> deleteMessage(String key) async {
await _dbRef.child(key).remove();
}
Future<void> updateMessage(String key, String newText) async {
await _dbRef.child(key).update({'text': newText});
}
Stream<DatabaseEvent> getMessagesStream() {
return _dbRef.onValue;
}
}
import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'firebase_service.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final TextEditingController _controller = TextEditingController();
final FirebaseService _firebaseService = FirebaseService();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Firebase Realtime Database')),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
TextField(
controller: _controller,
decoration: InputDecoration(labelText: 'Entrez un message'),
),
SizedBox(height: 10),
ElevatedButton(
onPressed: _writeData,
child: Text('Écrire dans Firebase'),
),
SizedBox(height: 20),
Expanded(child: _buildMessageList()),
],
),
),
);
}
void _writeData() {
String message = _controller.text.trim();
if (message.isNotEmpty) {
_firebaseService.writeMessage(message);
_controller.clear();
}
}
Widget _buildMessageList() {
return StreamBuilder<DatabaseEvent>(
stream: _firebaseService.getMessagesStream(),
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!.snapshot.value != null) {
Map<dynamic, dynamic> messages =
snapshot.data!.snapshot.value as Map<dynamic, dynamic>;
List<MapEntry<dynamic, dynamic>> entries = messages.entries.toList().reversed.toList();
return ListView.builder(
itemCount: entries.length,
itemBuilder: (context, index) {
String key = entries[index].key;
String text = entries[index].value['text'] ?? '';
return ListTile(
title: Text(text),
trailing: PopupMenuButton<String>(
onSelected: (value) {
if (value == 'modifier') {
_editMessageDialog(key, text);
} else if (value == 'supprimer') {
_firebaseService.deleteMessage(key);
}
},
itemBuilder: (context) => [
PopupMenuItem(value: 'modifier', child: Text('Modifier')),
PopupMenuItem(value: 'supprimer', child: Text('Supprimer')),
],
),
);
},
);
} else {
return Center(child: Text('Aucun message trouvé.'));
}
},
);
}
void _editMessageDialog(String key, String currentText) {
TextEditingController editController = TextEditingController(text: currentText);
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Modifier le message'),
content: TextField(
controller: editController,
decoration: InputDecoration(labelText: 'Nouveau message'),
),
actions: [
TextButton(
child: Text('Annuler'),
onPressed: () => Navigator.of(context).pop(),
),
ElevatedButton(
child: Text('Enregistrer'),
onPressed: () {
String newText = editController.text.trim();
if (newText.isNotEmpty) {
_firebaseService.updateMessage(key, newText);
}
Navigator.of(context).pop();
},
),
],
);
},
);
}
}