Développement local pour vos applications Flutter à l'aide de Firebase Emulator Suite

1. Avant de commencer

Dans cet atelier de programmation, vous apprendrez à utiliser Firebase Emulator Suite avec Flutter lors du développement local. Vous apprendrez comment utiliser l'authentification par mot de passe de courrier électronique via Emulator Suite, et comment lire et écrire des données sur l'émulateur Firestore. Enfin, vous travaillerez à l'importation et à l'exportation de données à partir des émulateurs, pour travailler avec les mêmes données falsifiées à chaque fois que vous reviendrez au développement.

Conditions préalables

Cet atelier de programmation suppose que vous possédez une certaine expérience de Flutter. Sinon, vous voudrez peut-être d’abord apprendre les bases. Les liens suivants sont 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 n'êtes pas familier avec la console Firebase, ou si vous êtes complètement nouveau sur 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 aura un écran de connexion et un écran qui vous permettra de lire les entrées de journal passées et d'en créer de nouvelles.

cd5c4753bbee8af.png8cb4d21f656540bf.png

Ce que vous apprendrez

Vous apprendrez comment commencer à utiliser Firebase et comment intégrer et utiliser la suite Firebase Emulator dans votre flux de travail de développement Flutter. Ces sujets Firebase 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 Firebase Emulator Suite. Il n'y aura pas de discussions approfondies sur l'authentification Firebase ou Firestore. Si vous n'êtes pas familier avec ces sujets, nous vous recommandons de commencer par l' atelier de programmation Apprendre à connaître Firebase pour Flutter .

Ce dont vous aurez besoin

  • Connaissance pratique de Flutter et du SDK installé
  • Éditeurs de texte Intellij JetBrains ou VS Code
  • Navigateur Google Chrome (ou votre autre cible de développement préférée pour Flutter. Certaines commandes de terminal de cet atelier de programmation supposeront que vous exécutez votre application sur Chrome)

2. Créez et configurez un projet Firebase

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

Créer un projet Firebase

  1. Connectez-vous à la console Firebase.
  2. Dans la console Firebase, cliquez sur Ajouter un projet (ou Créer un projet ) et saisissez un nom pour votre projet Firebase (par exemple, " Firebase-Flutter-Codelab") .

fe6aeab3b91965ed.png

  1. Cliquez sur les options de création de projet. Acceptez les conditions de Firebase si vous y êtes invité. Ignorez la configuration de Google Analytics, car vous n'utiliserez pas Analytics pour cette application.

d1fcec48bf251eaa.png

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

L'application que vous créez utilise deux produits Firebase disponibles pour les applications Flutter :

  • Authentification Firebase 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 lorsque les données changent.

Ces deux produits nécessitent une configuration spéciale ou doivent être activés à l'aide de la console Firebase.

Activer Cloud Firestore

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

Activer Cloud Firestore :

  1. Dans la section Build 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 l'avertissement sur les règles de sécurité. Le mode test garantit que vous pouvez écrire librement dans la base de données pendant le développement. Cliquez sur Suivant . 6be00e26c72ea032.png
  4. Sélectionnez l'emplacement de votre base de données (vous pouvez simplement utiliser celui par défaut). Notez que cet emplacement ne pourra pas être modifié ultérieurement. 278656eefcfb0216.png
  5. Cliquez sur Activer .

3. Configurez l'application Flutter

Vous devrez télécharger le code de démarrage et installer la CLI Firebase avant de commencer.

Obtenez 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

Alternativement, si l'outil cli de GitHub est 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 est composée de deux projets Flutter. L'un d'entre eux s'appelle complete , auquel vous pouvez vous référer si vous souhaitez avancer ou faire référence à votre propre code. L'autre projet s'appelle 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 votre IDE préféré.

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 devrez donc l'installer.

Il existe différentes manières d'installer la CLI. Le moyen le plus simple, si vous utilisez MacOS ou Linux, est d'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. Connectez-vous à Firebase à l'aide de votre compte Google en exécutant la commande suivante :
firebase login
  1. Cette commande connecte votre machine locale à Firebase et vous donne accès à vos projets Firebase.
  1. Testez que la CLI est correctement installée et a accès à votre compte en répertoriant vos projets Firebase. Exécutez la commande suivante :
firebase projects:list
  1. La liste affichée doit être la même que celle des projets Firebase répertoriés dans la console Firebase . Vous devriez voir au moins Firebase-Flutter-Codelab.

Installez la CLI FlutterFire

La CLI FlutterFire est construite sur la CLI Firebase et facilite l'intégration d'un projet Firebase avec votre application Flutter.

Tout d'abord, installez 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

Utilisez Firebase CLI et FlutterFire CLI 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 avec seulement quelques commandes de terminal.

Tout d’abord, terminez la configuration de Firebase en exécutant ce qui suit :

firebase init

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

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

f11dcab439e6ac1e.png

  1. Maintenant, sélectionnez le projet que vous avez créé à une étape précédente : flutter-firebase-codelab.

3bdc0c6934991c25.png

  1. Ensuite, une série de questions vous sera posée sur la dénomination des fichiers qui seront générés. Je suggère d'appuyer sur "Entrée" pour chaque question pour sélectionner la valeur par défaut. 9bfa2d507e199c59.png
  2. Enfin, vous devrez configurer les émulateurs. Sélectionnez Firestore et Authentification dans la liste, puis appuyez sur « Entrée » pour chaque question sur les ports spécifiques à utiliser pour chaque émulateur. Vous devez sélectionner la valeur par défaut, Oui, lorsqu'on vous demande si vous souhaitez utiliser l'interface utilisateur de l'émulateur.

À la fin du processus, vous devriez voir une sortie qui ressemble à la capture d'écran suivante.

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

8544e41037637b07.png

Configurer FlutterFire

Ensuite, vous pouvez utiliser FlutterFire pour générer le code Dart nécessaire pour utiliser Firebase dans votre application Flutter.

flutterfire configure

Lorsque cette commande est exécutée, vous serez 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 invites auxquelles vous devrez répondre.

619b7aca6dc15472.png301c9534f594f472.png

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

12199a85ade30459.png

Ajouter des packages Firebase à l'application Flutter

La dernière étape de configuration consiste à ajouter les packages Firebase pertinents à votre projet Flutter. Dans le terminal, assurez-vous que vous êtes à la racine du projet Flutter à flutter-codelabs/firebase-emulator-suite/start . Ensuite, exécutez 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. Activation des émulateurs Firebase

Jusqu'à présent, l'application Flutter et votre projet Firebase sont configurés pour pouvoir utiliser les émulateurs, mais vous devez toujours 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. Presque universellement, si vous travaillez avec Firebase dans une application Flutter, vous souhaitez 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. Étant donné que kDebugMode est une valeur constante, le compilateur Dart sait qu'il doit supprimer complètement ce bloc de code en mode version.

Démarrez les émulateurs

Vous devez démarrer les émulateurs avant de démarrer l'application Flutter. Tout d’abord, démarrez les émulateurs en exécutant ceci dans le terminal :

firebase emulators:start

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

bb7181eb70829606.png

Cette sortie vous indique quels émulateurs sont en cours d'exécution et où vous pouvez aller pour voir les émulateurs. Tout d’abord, consultez l’interface utilisateur de l’émulateur sur localhost:4000 .

11563f4c7216de81.png

Il s'agit de la page d'accueil de l'interface utilisateur de l'émulateur local. Il répertorie tous les émulateurs disponibles et chacun est étiqueté avec un statut activé ou désactivé.

5. L'émulateur Firebase Auth

Le premier émulateur que vous utiliserez est l’émulateur d’authentification. Commencez avec l'émulateur Auth en cliquant sur « Aller à l'émulateur » sur la carte d'authentification dans l'interface utilisateur, et vous verrez une page qui ressemble à ceci :

3c1bfded40733189.png

Cette page présente des similitudes avec la page de la console Web d'authentification. Il comporte un tableau répertoriant les utilisateurs comme la console en ligne et vous permet d'ajouter manuellement des utilisateurs. Une grande différence ici est que la seule option de méthode d'authentification disponible sur les émulateurs est via e-mail et mot de passe. C’est suffisant pour le développement local.

Ensuite, vous suivrez le processus d'ajout d'un utilisateur à l'émulateur Firebase Auth, puis vous connecterez cet utilisateur via l'interface utilisateur Flutter.

Ajouter un utilisateur

Cliquez sur le bouton « Ajouter un utilisateur » et remplissez le formulaire avec ces informations :

  • Nom d’affichage : Dash
  • Courriel : dash@email.com
  • Mot de passe : mot de passe

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

connecté_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 ressemble à ceci :

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'e-mail et le mot de passe que vous avez créés dans l'émulateur d'authentification. Et dans la ligne suivante, la ligne if(true) a été remplacée par du code qui vérifie si state.user est nul. Le code dans AppClass apporte plus de lumière à ce sujet.

app_state.dart

Deux parties du code dans AppState doivent être mises à jour. Tout d’abord, donnez au membre de la classe AppState.user le type User du package firebase_auth , plutôt que le type Object .

Deuxièmement, 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 de 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 , qui sont discutées dans un instant.

Il s'agit du code de base nécessaire pour connecter un utilisateur avec un e-mail et un mot de passe dans Firebase Auth. Il appelle FirebaseAuth pour se connecter, ce qui renvoie un objet Future<UserCredential> . Une fois le futur terminé, ce code vérifie s'il y a un User attaché au UserCredential . S'il y a un utilisateur sur l'objet d'informations d'identification, alors un utilisateur s'est connecté avec succès et la propriété AppState.user peut être définie. Si ce n'est pas le cas, il y a eu une erreur et elle est imprimée.

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

À FAIRE : Icône d'action – Rechargez votre application, puis appuyez sur le bouton de connexion lors du rendu. Cela amène l'application à accéder à une page indiquant "Bienvenue, personne !" au sommet. L'authentification doit fonctionner, car elle vous permet de naviguer vers cette page, mais une mise à jour mineure doit être effectuée logged_in_view.dart pour afficher le nom réel de l'utilisateur.

connecté_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(
 // ...

Maintenant, cette ligne récupère le displayName de la propriété User sur 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 « Bienvenue, Dash ! » lorsque vous vous connectez, plutôt que TODO .

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

Tout d’abord, consultez l’émulateur Firestore. Sur la page d'accueil de l'interface utilisateur de l'émulateur ( localhost:4000 ), cliquez sur "Aller à l'émulateur" sur la carte Firestore. Ça devrait ressembler à ça:

Émulateur :

791fce7dc137910a.png

Console Firebase :

e0dde9aea34af050.png

Si vous avez de l'expérience avec Firestore, vous remarquerez que cette page ressemble à la page Firestore de la console Firebase. Il existe cependant quelques différences notables.

  1. Vous pouvez effacer toutes les données en appuyant simplement sur un bouton. 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, il est facile de le clarifier.
  2. Il y a un onglet "Demandes". Cet onglet vous permet de surveiller les requêtes entrantes adressées à cet émulateur. Je discuterai de cet onglet plus en détail dans un instant.
  3. Il n'y a pas d'onglets pour les règles, les index ou l'utilisation. 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.

Pour résumer cette liste, cette version de Firestore fournit davantage d'outils utiles lors du développement et supprime les outils nécessaires à la production.

Écrire sur Firestore

Avant de discuter de l'onglet « Demandes » dans l'émulateur, faites d'abord une demande. Cela nécessite des mises à jour du code. Commencez par câbler le formulaire dans l'application pour rédiger une nouvelle Entry de journal dans Firestore.

Le flux de haut niveau pour soumettre une Entry est le suivant :

  1. L'utilisateur remplit le formulaire et appuie sur le bouton Submit
  2. L'interface utilisateur appelle AppState.writeEntryToFirebase
  3. AppState.writeEntryToFirebase ajoute une entrée à Firebase

Aucun code impliqué dans l'étape 1 ou 2 n'a besoin d'être modifié. Le seul code qui doit être ajouté 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 appelée « Entries » dans Firestore. Il ajoute ensuite une nouvelle entrée, qui doit être de type Map<String, String> .

Dans ce cas, la collection « Entries » dans Firestore n'existait pas, Firestore en a donc créé une.

Une fois ce code ajouté, rechargez à chaud ou redémarrez votre application, connectez-vous et accédez à la vue EntryForm . Vous pouvez remplir le formulaire avec Strings de votre choix. (Le champ Date acceptera n'importe quelle chaîne, car il a été simplifié pour cet atelier de programmation. Il n'a pas de validation forte et ne se soucie en aucune façon des objets DateTime .)

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

L'onglet requêtes dans l'émulateur Firestore

Dans l'interface utilisateur, accédez à l'émulateur Firestore et regardez l'onglet "Données". Vous devriez voir qu'il y a maintenant une collection à la racine de votre base de données appelée "Entries". Cela devrait avoir un document contenant les mêmes informations que vous avez saisies dans le formulaire.

a978fb34fb8a83da.png

Cela confirme que AppState.writeEntryToFirestore a fonctionné et vous pouvez désormais explorer davantage la demande dans l'onglet Requêtes. Cliquez sur cet onglet maintenant.

Requêtes d'émulateur Firestore

Ici, vous devriez voir une liste qui ressemble à ceci :

f0b37f0341639035.png

Vous pouvez cliquer sur l’un de ces éléments de liste et voir de nombreuses informations utiles. Cliquez sur l'élément de liste CREATE qui correspond à votre demande pour créer une nouvelle écriture de journal. Vous verrez un nouveau tableau qui ressemble à ceci :

385d62152e99aad4.png

Comme mentionné, l'émulateur Firestore fournit des outils pour développer les règles de sécurité de votre application. Cette vue montre exactement quelle ligne de vos règles de sécurité cette demande a réussi (ou a échoué, si tel était le cas). Dans une application plus robuste, les règles de sécurité peuvent se développer et comporter plusieurs contrôles d'autorisation. Cette vue est utilisée pour aider à écrire et déboguer ces règles d'autorisation.

Il fournit également un moyen simple d’inspecter chaque élément de cette demande, y compris les métadonnées et les données d’authentification. Ces données sont utilisées pour écrire des règles d'autorisation complexes.

Lecture depuis Firestore

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

Ce code fonctionne conjointement avec StreamController et Stream appelés respectivement AppState._entriesStreamController et AppState.entries . Ce code est déjà écrit, tout comme tout le code nécessaire dans l'interface utilisateur 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 modifie tous ses documents enfants en un objet que notre application peut utiliser ( Entry ). Ensuite, il ajoute ces entrées au StreamController appelé _entriesStreamController (que l'interface utilisateur écoute). Ce code est la seule mise à jour requise.

Enfin, rappelez-vous que la méthode AppState.logIn effectue un appel à _listenForEntries , qui démarre le processus d'écoute après la connexion d'un utilisateur.

// ...
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!');
 }
}
// ...

Maintenant, lancez l'application. Ça devrait ressembler à ça:

b8a31c7a8900331.gif

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

Les émulateurs Firebase prennent en charge l'importation et l'exportation de données. L'utilisation des importations et des exportations vous permet de poursuivre le développement avec les mêmes données lorsque vous faites une pause dans le développement, puis que vous le reprenez. Vous pouvez également valider des fichiers de données sur git, et les autres développeurs avec lesquels vous travaillez disposeront des mêmes données avec lesquelles travailler.

Exporter les données de l'émulateur

Tout d’abord, exportez 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 entrez 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 n'importe quel nom pour ce répertoire.

Lorsque vous exécutez cette commande, vous verrez ce résultat dans le terminal où vous avez exécuté la commande :

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

Et si vous passez à la fenêtre du terminal où les émulateurs sont exécutés, vous verrez cette sortie :

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

Et enfin, si vous regardez dans le répertoire de votre projet, vous devriez voir un répertoire appelé ./emulators_data , qui contient des fichiers JSON , entre autres fichiers de métadonnées, avec les données que vous avez enregistrées.

Importer des données d'émulateur

Vous pouvez désormais importer ces données dans le cadre de votre flux de travail de développement et commencer 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 lui indiquant quelles données importer :

firebase emulators:start --import ./emulators_data

Lorsque les émulateurs sont opérationnels, accédez à l'interface utilisateur de l'émulateur sur localhost:4000 et vous devriez voir les mêmes données 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, plutôt que de penser à exporter les données à 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 travaillerez avec les émulateurs de ce projet. Vous pouvez également spécifier un répertoire différent comme argument de –export-on-exit flag , mais il s'agira par défaut du répertoire transmis à –import .

Vous pouvez également utiliser n’importe quelle combinaison de ces options. Voici la note de la documentation : Le répertoire d'exportation peut être spécifié avec cet indicateur : firebase emulators:start --export-on-exit=./saved-data . Si --import est utilisé, le chemin d'exportation est le même par défaut ; par exemple : firebase emulators:start --import=./data-path --export-on-exit . Enfin, si vous le souhaitez, transmettez différents chemins de répertoire aux indicateurs --import et --export-on-exit .

8. Félicitations !

Vous avez terminé Soyez opérationnel avec l’émulateur Firebase et Flutter. Vous pouvez trouver le code complété pour ce Codelab dans le répertoire "complete" sur github : Flutter Codelabs

Ce que nous avons couvert

  • Configuration d'une application Flutter pour utiliser Firebase
  • Mettre en place un projet Firebase
  • CLI FlutterFire
  • CLI Firebase
  • Émulateur d'authentification Firebase
  • Émulateur Firebase Firestore
  • Importation et exportation de données d'émulateur

Prochaines étapes

Apprendre encore plus

Sparky est fier de toi !

2a0ad195769368b1.gif