Développement local pour vos applications Flutter à l'aide de la suite d'émulateurs Firebase

1. Avant de commencer

Dans cet atelier de programmation, vous apprendrez à utiliser la suite d'émulateurs Firebase avec Flutter lors du développement local. Vous apprendrez à utiliser l'authentification par adresse e-mail et mot de passe via la suite d'émulateurs, et à lire et écrire des données dans l'émulateur Firestore. Enfin, vous apprendrez à importer et exporter des données depuis les émulateurs, afin de travailler avec les mêmes données fictives chaque fois que vous revenez au développement.

Prérequis

Cet atelier de programmation suppose que vous avez une certaine expérience de Flutter. Dans le cas contraire, vous devriez d'abord vous familiariser avec ses principes de base. Les liens suivants proposent des informations utiles :

Vous devez également avoir une certaine expérience de Firebase, mais ce n'est pas grave si vous n'avez jamais ajouté Firebase à un projet Flutter. Si vous ne connaissez pas la console Firebase ou si vous n'avez jamais utilisé Firebase, consultez d'abord les liens suivants :

Ce que vous allez créer

Cet atelier de programmation vous guide dans la création d'une application de journalisation simple. L'application comporte un écran de connexion, ainsi qu'un écran qui vous permet de lire les entrées de journal précédentes et d'en créer de nouvelles.

cd5c4753bbee8af.png 8cb4d21f656540bf.png

Points abordés

Vous apprendrez à utiliser Firebase, et à intégrer et utiliser la suite d'émulateurs Firebase dans votre workflow de développement Flutter. Voici les thèmes Firebase qui seront abordés :

Notez que ces sujets sont abordés dans la mesure où ils sont nécessaires pour couvrir la suite d'émulateurs Firebase. Cet atelier de programmation se concentre sur l'ajout d'un projet Firebase à votre application Flutter et sur le développement à l'aide de la suite d'émulateurs Firebase. Les discussions sur Firebase Authentication ou Firestore ne seront pas approfondies. Si vous ne connaissez pas bien ces sujets, nous vous recommandons de commencer par l'atelier de programmation Découvrez Firebase pour Flutter.

Prérequis

  • Connaissances pratiques de Flutter et du SDK installé
  • Éditeurs de texte IntelliJ JetBrains ou VS Code
  • Navigateur Google Chrome (ou autre cible de développement de votre choix pour Flutter). Certaines commandes de terminal de cet atelier de programmation supposent que vous exécutez votre application sur Chrome.

2. Créer et configurer un projet Firebase

La première tâche à accomplir consiste à créer un projet Firebase dans la console Web de Firebase. La grande majorité de cet atelier de programmation se concentrera sur la suite d'émulateurs, qui utilise une interface utilisateur exécutée localement. Toutefois, vous devez d'abord configurer un projet Firebase complet.

Créer un projet Firebase

  1. Connectez-vous à la console Firebase à l'aide de votre compte Google.
  2. Cliquez sur le bouton pour créer un projet, puis saisissez un nom de projet (par exemple, Firebase-Flutter-Codelab).
  3. Cliquez sur Continuer.
  4. Si vous y êtes invité, lisez et acceptez les Conditions d'utilisation de Firebase, puis cliquez sur Continuer.
  5. (Facultatif) Activez l'assistance IA dans la console Firebase (appelée "Gemini dans Firebase").
  6. Pour cet atelier de programmation, vous n'avez pas besoin de Google Analytics. Désactivez donc l'option Google Analytics.
  7. Cliquez sur Créer un projet, attendez que votre projet soit provisionné, puis cliquez sur Continuer.

Pour en savoir plus sur les projets Firebase, consultez Comprendre les projets Firebase.

Configurer les produits Firebase

L'application que vous êtes en train de créer utilise deux produits Firebase disponibles pour les applications Flutter :

  • Firebase Authentication, pour permettre à vos utilisateurs de se connecter à votre application.
  • Cloud Firestore, pour enregistrer des données structurées sur le cloud et recevoir une notification instantanée en cas de modification des données.

Ces deux produits nécessitent une configuration particulière ou doivent être activés via la console Firebase.

Activer Cloud Firestore

L'application Flutter utilise Cloud Firestore pour enregistrer les entrées de journal.

Activez Cloud Firestore :

  1. Dans la section Créer de la console Firebase, cliquez sur Cloud Firestore.
  2. Cliquez sur Créer une base de données. 99e8429832d23fa3.png
  3. Sélectionnez l'option Démarrer en mode test. Lisez la clause de non-responsabilité concernant les règles de sécurité. Le mode test vous permet d'écrire librement dans la base de données pendant le développement. Cliquez sur Suivant. 6be00e26c72ea032.png
  4. Sélectionnez l'emplacement de la base de données (vous pouvez utiliser celui par défaut). Notez que vous ne pourrez pas modifier cet emplacement ultérieurement. 278656eefcfb0216.png
  5. Cliquez sur Activer.

3. Configurer l'application Flutter

Avant de commencer, vous devez télécharger le code de démarrage et installer la CLI Firebase.

Télécharger le code de démarrage

Clonez le dépôt GitHub à partir de la ligne de commande :

git clone https://github.com/flutter/codelabs.git flutter-codelabs

Vous pouvez également utiliser l'outil CLI de GitHub si vous l'avez installé :

gh repo clone flutter/codelabs flutter-codelabs

L'exemple de code doit être cloné dans le répertoire flutter-codelabs, qui contient le code d'une collection d'ateliers de programmation. Le code de cet atelier de programmation se trouve dans flutter-codelabs/firebase-emulator-suite.

La structure de répertoires sous flutter-codelabs/firebase-emulator-suite se compose de deux projets Flutter. L'un d'eux s'appelle complete. Vous pouvez vous y référer si vous souhaitez passer à la suite ou comparer votre propre code. L'autre projet est appelé start.

Le code avec lequel vous souhaitez commencer se trouve dans le répertoire flutter-codelabs/firebase-emulator-suite/start. Ouvrez ou importez ce répertoire dans l'IDE de votre choix.

cd flutter-codelabs/firebase-emulator-suite/start

Installer la CLI Firebase

La CLI Firebase fournit des outils pour gérer vos projets Firebase. La CLI est requise pour utiliser Emulator Suite. Vous devez donc l'installer.

Il existe différentes façons d'installer la CLI. Si vous utilisez macOS ou Linux, le moyen le plus simple consiste à exécuter cette commande depuis votre terminal :

curl -sL https://firebase.tools | bash

Après avoir installé la CLI, vous devez vous authentifier auprès de Firebase.

  1. Exécutez la commande suivante pour vous connecter à Firebase avec votre compte Google :
firebase login
  1. Cette commande connecte votre machine locale à Firebase et vous donne accès à vos projets Firebase.
  1. Vérifiez que la CLI est correctement installée et qu'elle a accès à votre compte en listant vos projets Firebase. Exécutez la commande suivante :
firebase projects:list
  1. La liste affichée doit être identique à celle des projets Firebase listés dans la console Firebase. Au moins firebase-flutter-codelab devrait s'afficher.

Installer la CLI FlutterFire

La CLI FlutterFire est basée sur la CLI Firebase. Elle facilite l'intégration d'un projet Firebase à votre application Flutter.

Commencez par installer la CLI :

dart pub global activate flutterfire_cli

Assurez-vous que la CLI a été installée. Exécutez la commande suivante dans le répertoire du projet Flutter et assurez-vous que la CLI affiche le menu d'aide.

flutterfire --help

Utiliser la CLI Firebase et la CLI FlutterFire pour ajouter votre projet Firebase à votre application Flutter

Une fois les deux CLI installées, vous pouvez configurer des produits Firebase individuels (comme Firestore), télécharger les émulateurs et ajouter Firebase à votre application Flutter en quelques commandes de terminal.

Pour commencer, terminez la configuration de Firebase en exécutant la commande suivante :

firebase init

Cette commande vous guidera à travers une série de questions nécessaires à la configuration de votre projet. Les captures d'écran suivantes illustrent le flux :

  1. Lorsque vous êtes invité à sélectionner des fonctionnalités, choisissez "Firestore" et "Émulateurs". (Il n'y a pas d'option d'authentification, car elle n'utilise pas de configuration modifiable à partir des fichiers de votre projet Flutter.) fe6401d769be8f53.png
  2. Ensuite, sélectionnez "Utiliser un projet existant" lorsque vous y êtes invité.

f11dcab439e6ac1e.png

  1. Sélectionnez ensuite le projet que vous avez créé à l'étape précédente : flutter-firebase-codelab.

3bdc0c6934991c25.png

  1. Vous serez ensuite invité à répondre à une série de questions sur la façon de nommer les fichiers qui seront générés. Je vous suggère d'appuyer sur "Entrée" pour chaque question afin de sélectionner la valeur par défaut. 9bfa2d507e199c59.png
  2. Enfin, vous devez configurer les émulateurs. Sélectionnez Firestore et Authentication dans la liste, puis appuyez sur "Entrée" pour chaque question concernant les ports spécifiques à utiliser pour chaque émulateur. Vous devez sélectionner la valeur par défaut "Oui" lorsque vous êtes invité à utiliser l'interface utilisateur de l'émulateur.

À la fin du processus, un résultat semblable à la capture d'écran suivante devrait s'afficher.

Important : Votre résultat peut être légèrement différent du mien, comme le montre la capture d'écran ci-dessous, car la réponse à la dernière question sera "Non" par défaut si vous avez déjà téléchargé les émulateurs.

8544e41037637b07.png

Configurer FlutterFire

Vous pouvez ensuite utiliser FlutterFire pour générer le code Dart nécessaire à l'utilisation de Firebase dans votre application Flutter.

flutterfire configure

Lorsque vous exécutez cette commande, vous êtes invité à sélectionner le projet Firebase que vous souhaitez utiliser et les plates-formes que vous souhaitez configurer. Dans cet atelier de programmation, les exemples utilisent Flutter Web, mais vous pouvez configurer votre projet Firebase pour utiliser toutes les options.

Les captures d'écran suivantes montrent les questions auxquelles vous devrez répondre.

619b7aca6dc15472.png 301c9534f594f472.png

Cette capture d'écran montre le résultat à la fin du processus. Si vous connaissez Firebase, vous remarquerez que vous n'avez pas eu à créer d'applications dans la console, car la CLI FlutterFire l'a fait pour vous.

12199a85ade30459.png

Ajouter des packages Firebase à une application Flutter

La dernière étape de configuration consiste à ajouter les packages Firebase pertinents à votre projet Flutter. Dans le terminal, assurez-vous de vous trouver à la racine du projet Flutter, à l'adresse flutter-codelabs/firebase-emulator-suite/start. Exécutez ensuite les trois commandes suivantes :

flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add cloud_firestore

Ce sont les seuls packages que vous utiliserez dans cette application.

4. Activer les émulateurs Firebase

Jusqu'à présent, l'application Flutter et votre projet Firebase sont configurés pour pouvoir utiliser les émulateurs. Toutefois, vous devez encore indiquer au code Flutter de rediriger les requêtes Firebase sortantes vers les ports locaux.

Tout d'abord, ajoutez le code d'initialisation de Firebase et le code de configuration de l'émulateur à la fonction main dans main.dart..

main.dart

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

import 'app_state.dart';
import 'firebase_options.dart';
import 'logged_in_view.dart';
import 'logged_out_view.dart';


void main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await Firebase.initializeApp(
   options: DefaultFirebaseOptions.currentPlatform,
 );

 if (kDebugMode) {
   try {
     FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080);
     await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
   } catch (e) {
     // ignore: avoid_print
     print(e);
   }
 }

 runApp(MyApp());
}

Les premières lignes de code initialisent Firebase. Dans la quasi-totalité des cas, si vous utilisez Firebase dans une application Flutter, vous devez commencer par appeler WidgetsFlutterBinding.ensureInitialized et Firebase.initializeApp.

Ensuite, le code commençant par la ligne if (kDebugMode) indique à votre application de cibler les émulateurs plutôt qu'un projet Firebase de production. kDebugMode garantit que le ciblage des émulateurs ne se produira que si vous êtes dans un environnement de développement. Comme kDebugMode est une valeur constante, le compilateur Dart sait qu'il doit supprimer complètement ce bloc de code en mode Release.

Démarrer les émulateurs

Vous devez démarrer les émulateurs avant de démarrer l'application Flutter. Commencez par démarrer les émulateurs en exécutant la commande suivante dans le terminal :

firebase emulators:start

Cette commande démarre les émulateurs et expose les ports localhost avec lesquels nous pouvons interagir. Lorsque vous exécutez cette commande, vous devriez obtenir un résultat semblable à celui-ci :

bb7181eb70829606.png

Ce résultat vous indique les émulateurs en cours d'exécution et l'emplacement où vous pouvez les voir. Commencez par consulter l'UI de l'émulateur à l'adresse localhost:4000.

11563f4c7216de81.png

Il s'agit de la page d'accueil de l'UI de l'émulateur local. Elle liste tous les émulateurs disponibles, chacun étant associé à l'état "activé" ou "désactivé".

5. Émulateur Firebase Auth

Le premier émulateur que vous utiliserez est l'émulateur d'authentification. Commencez par l'émulateur Auth en cliquant sur "Go to emulator" (Accéder à l'émulateur) sur la carte Authentication (Authentification) de l'UI. Vous verrez une page semblable à celle-ci :

3c1bfded40733189.png

Cette page présente des similitudes avec la page de la console Web Auth. Elle comporte un tableau listant les utilisateurs comme la console en ligne et vous permet d'ajouter manuellement des utilisateurs. La principale différence ici est que la seule option de méthode d'authentification disponible sur les émulateurs est celle par e-mail et mot de passe. Cela suffit pour le développement local.

Vous allez ensuite apprendre à ajouter un utilisateur à l'émulateur Firebase Auth, puis à le connecter via l'interface utilisateur Flutter.

Ajouter un utilisateur

Cliquez sur le bouton "Ajouter un utilisateur", puis remplissez le formulaire avec les informations suivantes :

  • Nom à afficher : Dash
  • Adresse e-mail : dash@email.com
  • Mot de passe : dashword

Envoyez le formulaire. Vous verrez que le tableau inclut désormais un utilisateur. Vous pouvez maintenant mettre à jour le code pour vous connecter avec cet utilisateur.

logged_out_view.dart

Le seul code du widget LoggedOutView qui doit être mis à jour se trouve dans le rappel déclenché lorsqu'un utilisateur appuie sur le bouton de connexion. Mettez à jour le code pour qu'il se présente comme suit :

class LoggedOutView extends StatelessWidget {
 final AppState state;
 const LoggedOutView({super.key, required this.state});
 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: const Text('Firebase Emulator Suite Codelab'),
     ),
     body: Center(
       child: Column(
         mainAxisAlignment: MainAxisAlignment.center,
         children: [
          Text(
           'Please log in',
            style: Theme.of(context).textTheme.displaySmall,
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: ElevatedButton(
             onPressed: () async {
              await state.logIn('dash@email.com', 'dashword').then((_) {
                if (state.user != null) {
                 context.go('/');
                }
              });
              },
              child: const Text('Log In'),
          ),
        ),
      ],
    ),
   ),
  );
 }
}

Le code mis à jour remplace les chaînes TODO par l'adresse e-mail et le mot de passe que vous avez créés dans l'émulateur Auth. Sur la ligne suivante, la ligne if(true) a été remplacée par du code qui vérifie si state.user est nul. Le code de AppClass apporte plus de précisions à ce sujet.

app_state.dart

Deux parties du code dans AppState doivent être mises à jour. Commencez par attribuer au membre de classe AppState.user le type User du package firebase_auth, plutôt que le type Object.

Ensuite, remplissez la méthode AppState.login comme indiqué ci-dessous :

import 'dart:async';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

import 'entry.dart';

class AppState {
 AppState() {
   _entriesStreamController = StreamController.broadcast(onListen: () {
     _entriesStreamController.add([
       Entry(
         date: '10/09/2022',
         text: lorem,
         title: '[Example] My Journal Entry',
       )
     ]);
   });
 }

 User? user; // <-- changed variable type
 Stream<List<Entry>> get entries => _entriesStreamController.stream;
 late final StreamController<List<Entry>> _entriesStreamController;

 Future<void> logIn(String email, String password) async {
   final credential = await FirebaseAuth.instance
       .signInWithEmailAndPassword(email: email, password: password);
   if (credential.user != null) {
     user = credential.user!;
     _listenForEntries();
   } else {
     print('no user!');
   }
 } 
 // ...
}

La définition du type pour l'utilisateur est désormais User?. Cette classe User provient de Firebase Auth et fournit les informations nécessaires, telles que User.displayName, dont nous parlerons plus en détail.

Il s'agit du code de base nécessaire pour connecter un utilisateur avec une adresse e-mail et un mot de passe dans Firebase Authentication. Il appelle FirebaseAuth pour se connecter, ce qui renvoie un objet Future<UserCredential>. Lorsque le futur est terminé, ce code vérifie si un User est associé au UserCredential. Si un utilisateur est associé à l'objet d'identification, cela signifie qu'il s'est connecté et que la propriété AppState.user peut être définie. Si ce n'est pas le cas, une erreur s'est produite et est affichée.

Notez que la seule ligne de code de cette méthode qui est spécifique à cette application (plutôt qu'au code FirebaseAuth général) est l'appel à la méthode _listenForEntries, qui sera abordée à l'étape suivante.

TODO: Action Icon – Reload your app, and then press the Login button when it renders. L'application est alors redirigée vers une page affichant "Bienvenue, Personne !" en haut. L'authentification doit fonctionner, car elle vous a permis d'accéder à cette page. Toutefois, une petite modification doit être apportée à logged_in_view.dart pour afficher le nom réel de l'utilisateur.

logged_in_view.dart

Modifiez la première ligne de la méthode LoggedInView.build :

class LoggedInView extends StatelessWidget {
 final AppState state;
 LoggedInView({super.key, required this.state});

 final PageController _controller = PageController(initialPage: 1);

 @override
 Widget build(BuildContext context) {
   final name = state.user!.displayName ?? 'No Name';

   return Scaffold(
 // ...

Cette ligne récupère maintenant le displayName à partir de la propriété User de l'objet AppState. Ce displayName a été défini dans l'émulateur lorsque vous avez défini votre premier utilisateur. Votre application devrait maintenant afficher "Welcome back, Dash!" (Bon retour, Dash !) lorsque vous vous connectez, au lieu de TODO.

6. Lire et écrire des données dans l'émulateur Firestore

Commencez par consulter l'émulateur Firestore. Sur la page d'accueil de l'interface utilisateur de l'émulateur (localhost:4000), cliquez sur "Go to emulator" (Accéder à l'émulateur) sur la fiche Firestore. Elle devrait se présenter comme ceci :

Émulateur :

791fce7dc137910a.png

Console Firebase :

e0dde9aea34af050.png

Si vous avez déjà utilisé Firestore, vous remarquerez que cette page ressemble à la page Firestore de la console Firebase. Il existe toutefois quelques différences notables.

  1. Vous pouvez effacer toutes les données en un seul geste. Cela serait dangereux avec les données de production, mais est utile pour une itération rapide. Si vous travaillez sur un nouveau projet et que votre modèle de données change, vous pouvez facilement le supprimer.
  2. Il existe un onglet "Demandes". Cet onglet vous permet de regarder les requêtes entrantes adressées à cet émulateur. Nous aborderons cet onglet plus en détail dans un instant.
  3. Les onglets "Règles", "Index" et "Utilisation" ne sont pas disponibles. Il existe un outil (abordé dans la section suivante) qui permet d'écrire des règles de sécurité, mais vous ne pouvez pas définir de règles de sécurité pour l'émulateur local.

En résumé, cette version de Firestore fournit davantage d'outils utiles pendant le développement et supprime ceux nécessaires en production.

Écrire dans Firestore

Avant de parler de l'onglet "Requests" (Requêtes) de l'émulateur, commençons par effectuer une requête. Cela nécessite des mises à jour du code. Commencez par relier le formulaire de l'application pour écrire un nouveau journal Entry à Firestore.

Voici la procédure générale à suivre pour envoyer une Entry :

  1. L'utilisateur a rempli le formulaire et appuyé sur le bouton Submit.
  2. L'UI appelle AppState.writeEntryToFirebase
  3. AppState.writeEntryToFirebase ajoute une entrée à Firebase.

Aucune modification n'est nécessaire pour le code des étapes 1 et 2. Le seul code à ajouter pour l'étape 3 sera ajouté dans la classe AppState. Apportez la modification suivante à AppState.writeEntryToFirebase.

app_state.dart

import 'dart:async';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

import 'entry.dart';

class AppState {
 AppState() {
   _entriesStreamController = StreamController.broadcast(onListen: () {
     _entriesStreamController.add([
       Entry(
         date: '10/09/2022',
         text: lorem,
         title: '[Example] My Journal Entry',
       )
     ]);
   });
 }

 User? user;
 Stream<List<Entry>> get entries => _entriesStreamController.stream;
 late final StreamController<List<Entry>> _entriesStreamController;

 Future<void> logIn(String email, String password) async {
   final credential = await FirebaseAuth.instance
       .signInWithEmailAndPassword(email: email, password: password);
   if (credential.user != null) {
     user = credential.user!;
     _listenForEntries();
   } else {
     print('no user!');
   }
 }

 void writeEntryToFirebase(Entry entry) {
   FirebaseFirestore.instance.collection('Entries').add(<String, String>{
     'title': entry.title,
     'date': entry.date.toString(),
     'text': entry.text,
   });
 }
 // ...
}

Le code de la méthode writeEntryToFirebase récupère une référence à la collection "Entries" dans Firestore. Il ajoute ensuite une entrée de type Map<String, String>.

Dans ce cas, la collection "Entries" n'existait pas dans Firestore, qui l'a donc créée.

Une fois ce code ajouté, effectuez une actualisation à chaud ou redémarrez votre application, connectez-vous, puis accédez à la vue EntryForm. Vous pouvez remplir le formulaire avec les Strings de votre choix. (Le champ "Date" accepte n'importe quelle chaîne, car il a été simplifié pour cet atelier de programmation. Il ne comporte pas de validation forte et ne se soucie pas des objets DateTime de quelque manière que ce soit.)

Appuyez sur "Envoyer" dans le formulaire. Rien ne se passe dans l'application, mais vous pouvez voir votre nouvelle entrée dans l'interface utilisateur de l'émulateur.

Onglet "Requests" (Requêtes) de l'émulateur Firestore

Dans l'UI, accédez à l'émulateur Firestore, puis consultez l'onglet "Données". Vous devriez voir qu'une collection appelée "Entries" (Entrées) se trouve désormais à la racine de votre base de données. Vous devriez y trouver un document contenant les informations que vous avez saisies dans le formulaire.

a978fb34fb8a83da.png

Cela confirme que AppState.writeEntryToFirestore a fonctionné. Vous pouvez maintenant explorer plus en détail la requête dans l'onglet "Requests" (Requêtes). Cliquez sur cet onglet.

Requêtes de l'émulateur Firestore

Une liste semblable à celle-ci devrait s'afficher :

f0b37f0341639035.png

Vous pouvez cliquer sur l'un de ces éléments pour afficher de nombreuses informations utiles. Cliquez sur l'élément de liste CREATE qui correspond à votre demande pour créer une entrée de journal. Un nouveau tableau s'affiche :

385d62152e99aad4.png

Comme mentionné précédemment, l'émulateur Firestore fournit des outils pour développer les règles de sécurité de votre application. Cette vue indique précisément la ligne de vos règles de sécurité par laquelle cette requête est passée (ou a échoué, le cas échéant). Dans une application plus robuste, les règles de sécurité peuvent se développer et comporter plusieurs vérifications d'autorisation. Cette vue permet d'écrire et de déboguer ces règles d'autorisation.

Il permet également d'inspecter facilement chaque élément de cette requête, y compris les métadonnées et les données d'authentification. Ces données sont utilisées pour rédiger des règles d'autorisation complexes.

Lire des données depuis Firestore

Firestore utilise la synchronisation des données pour envoyer les données mises à jour aux appareils connectés. Dans le code Flutter, vous pouvez écouter (ou vous abonner) les collections et les documents Firestore. Votre code sera averti chaque fois que les données changeront. Dans cette application, l'écoute des mises à jour Firestore s'effectue dans la méthode appelée AppState._listenForEntries.

Ce code fonctionne conjointement avec les StreamController et Stream appelés respectivement AppState._entriesStreamController et AppState.entries. Ce code est déjà écrit, tout comme celui nécessaire dans l'UI pour afficher les données de Firestore.

Mettez à jour la méthode _listenForEntries pour qu'elle corresponde au code ci-dessous :

app_state.dart

import 'dart:async';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

import 'entry.dart';

class AppState {
 AppState() {
   _entriesStreamController = StreamController.broadcast(onListen: () {
     _entriesStreamController.add([
       Entry(
         date: '10/09/2022',
         text: lorem,
         title: '[Example] My Journal Entry',
       )
     ]);
   });
 }

 User? user;
 Stream<List<Entry>> get entries => _entriesStreamController.stream;
 late final StreamController<List<Entry>> _entriesStreamController;

 Future<void> logIn(String email, String password) async {
   final credential = await FirebaseAuth.instance
       .signInWithEmailAndPassword(email: email, password: password);
   if (credential.user != null) {
     user = credential.user!;
     _listenForEntries();
   } else {
     print('no user!');
   }
 }

 void writeEntryToFirebase(Entry entry) {
   FirebaseFirestore.instance.collection('Entries').add(<String, String>{
     'title': entry.title,
     'date': entry.date.toString(),
     'text': entry.text,
   });
 }

 void _listenForEntries() {
   FirebaseFirestore.instance
       .collection('Entries')
       .snapshots()
       .listen((event) {
     final entries = event.docs.map((doc) {
       final data = doc.data();
       return Entry(
         date: data['date'] as String,
         text: data['text'] as String,
         title: data['title'] as String,
       );
     }).toList();

     _entriesStreamController.add(entries);
   });
 }
 // ...
}

Ce code écoute la collection "Entries" dans Firestore. Lorsque Firestore informe ce client qu'il existe de nouvelles données, il transmet ces données et le code dans _listenForEntries transforme tous ses documents enfants en un objet que notre application peut utiliser (Entry). Il ajoute ensuite ces entrées à la StreamController appelée _entriesStreamController (que l'UI écoute). Ce code est la seule mise à jour requise.

Enfin, rappelez-vous que la méthode AppState.logIn appelle _listenForEntries, qui lance le processus d'écoute une fois qu'un utilisateur s'est connecté.

// ...
Future<void> logIn(String email, String password) async {
 final credential = await FirebaseAuth.instance
     .signInWithEmailAndPassword(email: email, password: password);
 if (credential.user != null) {
   user = credential.user!;
   _listenForEntries();
 } else {
   print('no user!');
 }
}
// ...

Exécutez l'application. Elle devrait ressembler à ceci :

b8a31c7a8900331.gif

7. Exporter et importer des données dans l'émulateur

Les émulateurs Firebase sont compatibles avec l'importation et l'exportation de données. Les importations et les exportations vous permettent de continuer à développer avec les mêmes données lorsque vous faites une pause, puis reprenez le développement. Vous pouvez également valider des fichiers de données dans Git. Les autres développeurs avec lesquels vous travaillez auront ainsi les mêmes données.

Exporter les données de l'émulateur

Commencez par exporter les données de l'émulateur dont vous disposez déjà. Pendant que les émulateurs sont toujours en cours d'exécution, ouvrez une nouvelle fenêtre de terminal et saisissez la commande suivante :

firebase emulators:export ./emulators_data

.emulators_data est un argument qui indique à Firebase où exporter les données. Si le répertoire n'existe pas, il est créé. Vous pouvez utiliser le nom de votre choix pour ce répertoire.

Lorsque vous exécutez cette commande, le résultat suivant s'affiche dans le terminal :

i  Found running emulator hub for project flutter-firebase-codelab-d6b79 at http://localhost:4400
i  Creating export directory /Users/ewindmill/Repos/codelabs/firebase-emulator-suite/complete/emulators_data
i  Exporting data to: /Users/ewindmill/Repos/codelabs/firebase-emulator-suite/complete/emulators_data
✔  Export complete

Si vous passez à la fenêtre de terminal où les émulateurs sont en cours d'exécution, vous verrez le résultat suivant :

i  emulators: Received export request. Exporting data to /Users/ewindmill/Repos/codelabs/firebase-emulator-suite/complete/emulators_data.
✔  emulators: Export complete.

Enfin, si vous examinez le répertoire de votre projet, vous devriez y trouver un répertoire appelé ./emulators_data, qui contient des fichiers JSON, ainsi que d'autres fichiers de métadonnées, avec les données que vous avez enregistrées.

Importer des données de l'émulateur

Vous pouvez désormais importer ces données dans votre workflow de développement et reprendre là où vous vous étiez arrêté.

Tout d'abord, arrêtez les émulateurs s'ils sont en cours d'exécution en appuyant sur CTRL+C dans votre terminal.

Ensuite, exécutez la commande emulators:start que vous avez déjà vue, mais avec un indicateur indiquant les données à importer :

firebase emulators:start --import ./emulators_data

Une fois les émulateurs opérationnels, accédez à l'interface utilisateur de l'émulateur à l'adresse localhost:4000. Vous devriez voir les mêmes données que celles avec lesquelles vous travailliez auparavant.

Exporter automatiquement les données lors de la fermeture des émulateurs

Vous pouvez également exporter les données automatiquement lorsque vous quittez les émulateurs, au lieu de devoir vous en souvenir à la fin de chaque session de développement.

Lorsque vous démarrez vos émulateurs, exécutez la commande emulators:start avec deux indicateurs supplémentaires.

firebase emulators:start --import ./emulators_data --export-on-exit

Voilà ! Vos données seront désormais enregistrées et rechargées chaque fois que vous utiliserez les émulateurs pour ce projet. Vous pouvez également spécifier un autre répertoire comme argument de –export-on-exit flag, mais il sera défini par défaut sur le répertoire transmis à –import.

Vous pouvez également combiner ces options. Voici la remarque de la documentation : le répertoire d'exportation peut être spécifié avec l'option firebase emulators:start --export-on-exit=./saved-data. Si --import est utilisé, le chemin d'exportation est défini par défaut sur le même chemin, par exemple : firebase emulators:start --import=./data-path --export-on-exit. Enfin, si vous le souhaitez, transmettez différents chemins d'accès aux répertoires aux indicateurs --import et --export-on-exit.

8. Félicitations !

Vous avez terminé l'atelier "Premiers pas avec l'émulateur Firebase et Flutter". Vous trouverez le code final de cet atelier de programmation dans le répertoire "complete" sur GitHub : Ateliers de programmation Flutter.

Points abordés

  • Configurer une application Flutter pour utiliser Firebase
  • Configurer un projet Firebase
  • CLI FlutterFire
  • CLI Firebase
  • Émulateur Firebase Authentication
  • Émulateur Firebase Firestore
  • Importer et exporter des données de l'émulateur

Étapes suivantes

En savoir plus

Sparky est fier de vous !

2a0ad195769368b1.gif