1. Hinweis
In diesem Codelab erfahren Sie, wie Sie die Firebase Emulator Suite mit Flutter bei der lokalen Entwicklung verwenden. Sie erfahren, wie Sie die E-Mail-Passwort-Authentifizierung über die Emulator Suite verwenden und wie Sie Daten in den Firestore-Emulator lesen und schreiben. Schließlich lernen Sie, wie Sie Daten aus den Emulatoren importieren und exportieren, damit Sie bei jeder Rückkehr zur Entwicklung mit denselben gefälschten Daten arbeiten können.
Vorbereitung
In diesem Codelab wird davon ausgegangen, dass Sie bereits Erfahrung mit Flutter haben. Falls nicht, sollten Sie sich zuerst mit den Grundlagen vertraut machen. Die folgenden Links sind hilfreich:
Sie sollten auch etwas Erfahrung mit Firebase haben, aber es ist in Ordnung, wenn Sie Firebase noch nie einem Flutter-Projekt hinzugefügt haben. Wenn Sie die Firebase Console noch nicht kennen oder Firebase noch nie verwendet haben, lesen Sie zuerst die folgenden Artikel:
Was Sie erstellen
In diesem Codelab erfahren Sie, wie Sie eine einfache Tagebuch-App erstellen. Die Anwendung hat einen Anmeldebildschirm und einen Bildschirm, auf dem Sie frühere Tagebucheinträge lesen und neue erstellen können.
Lerninhalte
Sie erfahren, wie Sie mit Firebase beginnen und wie Sie die Firebase Emulator Suite in Ihren Flutter-Entwicklungsworkflow einbinden und verwenden. Folgende Firebase-Themen werden behandelt:
Diese Themen werden nur insofern behandelt, als sie für die Firebase-Emulatorsuite erforderlich sind. In diesem Codelab geht es darum, Ihrer Flutter-App ein Firebase-Projekt hinzuzufügen und die Firebase Emulator Suite zu verwenden. Es wird keine ausführliche Diskussion über Firebase Authentication oder Firestore geben. Wenn Sie mit diesen Themen nicht vertraut sind, empfehlen wir Ihnen, mit dem Codelab „Firebase für Flutter kennenlernen“ zu beginnen.
Voraussetzungen
- Grundkenntnisse in Flutter und installiertes SDK
- IntelliJ JetBrains- oder VS Code-Texteditoren
- Google Chrome-Browser (oder ein anderes bevorzugtes Entwicklungsziel für Flutter). Bei einigen Terminalbefehlen in diesem Codelab wird davon ausgegangen, dass Sie Ihre App in Chrome ausführen.
2. Firebase-Projekt erstellen und einrichten
Als Erstes müssen Sie ein Firebase-Projekt in der Webkonsole von Firebase erstellen. In diesem Codelab geht es hauptsächlich um die Emulator Suite, die eine lokal ausgeführte Benutzeroberfläche verwendet. Sie müssen aber zuerst ein vollständiges Firebase-Projekt einrichten.
Firebase-Projekt erstellen
- Melden Sie sich mit Ihrem Google-Konto in der Firebase Console an.
- Klicken Sie auf die Schaltfläche, um ein neues Projekt zu erstellen, und geben Sie dann einen Projektnamen ein (z. B.
Firebase-Flutter-Codelab
).
- Klicken Sie auf Weiter.
- Lesen und akzeptieren Sie bei Aufforderung die Firebase-Nutzungsbedingungen und klicken Sie dann auf Weiter.
- (Optional) Aktivieren Sie die KI-Unterstützung in der Firebase Console (als „Gemini in Firebase“ bezeichnet).
- Für dieses Codelab benötigen Sie kein Google Analytics. Deaktivieren Sie daher die Google Analytics-Option.
- Klicken Sie auf Projekt erstellen, warten Sie, bis Ihr Projekt bereitgestellt wurde, und klicken Sie dann auf Weiter.
Weitere Informationen zu Firebase-Projekten
Firebase-Produkte einrichten
Die App, die Sie erstellen, verwendet zwei Firebase-Produkte, die für Flutter-Apps verfügbar sind:
- Firebase Authentication, damit sich Nutzer in Ihrer App anmelden können.
- Cloud Firestore speichert strukturierte Daten in der Cloud und benachrichtigt Sie sofort, wenn sich Daten ändern.
Für diese beiden Produkte ist eine spezielle Konfiguration erforderlich oder sie müssen über die Firebase Console aktiviert werden.
Cloud Firestore aktivieren
Die Flutter-App verwendet Cloud Firestore zum Speichern von Tagebucheinträgen.
Cloud Firestore aktivieren:
- Klicken Sie in der Firebase Console im Abschnitt Build auf Cloud Firestore.
- Klicken Sie auf Datenbank erstellen.
- Wählen Sie die Option Im Testmodus starten aus. Lesen Sie den Haftungsausschluss zu den Sicherheitsregeln. Im Testmodus wird sichergestellt, dass Sie während der Entwicklung frei in die Datenbank schreiben können. Klicken Sie auf Weiter.
- Wählen Sie den Speicherort für Ihre Datenbank aus. Sie können auch den Standardwert verwenden. Dieser Standort kann später nicht mehr geändert werden.
- Klicken Sie auf Aktivieren.
3. Flutter-App einrichten
Bevor wir beginnen, müssen Sie den Startercode herunterladen und die Firebase CLI installieren.
Startcode abrufen
Klonen Sie das GitHub-Repository über die Befehlszeile:
git clone https://github.com/flutter/codelabs.git flutter-codelabs
Wenn Sie das CLI-Tool von GitHub installiert haben, können Sie alternativ Folgendes tun:
gh repo clone flutter/codelabs flutter-codelabs
Der Beispielcode sollte in das Verzeichnis flutter-codelabs
geklont werden, das den Code für eine Sammlung von Codelabs enthält. Der Code für dieses Codelab befindet sich in flutter-codelabs/firebase-emulator-suite
.
Die Verzeichnisstruktur unter flutter-codelabs/firebase-emulator-suite
besteht aus zwei Flutter-Projekten. Der erste heißt complete
. Sie können ihn verwenden, wenn Sie einen Abschnitt überspringen oder Ihren eigenen Code abgleichen möchten. Das andere Projekt heißt start
.
Der Code, mit dem Sie beginnen möchten, befindet sich im Verzeichnis flutter-codelabs/firebase-emulator-suite/start
. Öffnen oder importieren Sie das Verzeichnis in Ihrer bevorzugten IDE.
cd flutter-codelabs/firebase-emulator-suite/start
Firebase CLI installieren
Die Firebase CLI bietet Tools zum Verwalten Ihrer Firebase-Projekte. Die CLI ist für die Verwendung der Emulator Suite erforderlich. Sie müssen sie also installieren.
Es gibt verschiedene Möglichkeiten, die CLI zu installieren. Wenn Sie MacOS oder Linux verwenden, können Sie diesen Befehl am einfachsten in Ihrem Terminal ausführen:
curl -sL https://firebase.tools | bash
Nach der Installation der CLI müssen Sie sich bei Firebase authentifizieren.
- Melden Sie sich mit folgendem Befehl mit Ihrem Google-Konto in Firebase an:
firebase login
- Mit diesem Befehl wird Ihre lokale Maschine mit Firebase verbunden und Sie erhalten Zugriff auf Ihre Firebase-Projekte.
- Prüfen Sie, ob die CLI richtig installiert ist und Zugriff auf Ihr Konto hat, indem Sie Ihre Firebase-Projekte auflisten. Führen Sie dazu diesen Befehl aus:
firebase projects:list
- Die angezeigte Liste sollte mit den Firebase-Projekten in der Firebase Console übereinstimmen. Sie sollten mindestens „firebase-flutter-codelab“ sehen.
FlutterFire CLI installieren
Die FlutterFire CLI basiert auf der Firebase CLI und erleichtert die Integration eines Firebase-Projekts in Ihre Flutter-App.
Installieren Sie zuerst die Befehlszeile:
dart pub global activate flutterfire_cli
Prüfen Sie, ob die CLI installiert wurde. Führen Sie den folgenden Befehl im Flutter-Projektverzeichnis aus und prüfen Sie, ob die CLI das Hilfemenü ausgibt.
flutterfire --help
Firebase CLI und FlutterFire CLI verwenden, um Ihr Firebase-Projekt zu Ihrer Flutter-App hinzuzufügen
Nachdem Sie die beiden CLIs installiert haben, können Sie einzelne Firebase-Produkte (wie Firestore) einrichten, die Emulatoren herunterladen und Firebase mit nur wenigen Terminalbefehlen zu Ihrer Flutter-App hinzufügen.
Schließen Sie zuerst die Firebase-Einrichtung ab, indem Sie Folgendes ausführen:
firebase init
Sie werden durch eine Reihe von Fragen geführt, die für die Einrichtung Ihres Projekts erforderlich sind. Die folgenden Screenshots zeigen den Ablauf:
- Wenn Sie aufgefordert werden, Funktionen auszuwählen, wählen Sie „Firestore“ und „Emulators“ aus. Es gibt keine Authentifizierungsoption, da keine Konfiguration verwendet wird, die über Ihre Flutter-Projektdateien geändert werden kann.
- Wählen Sie als Nächstes „Vorhandenes Projekt verwenden“ aus, wenn Sie dazu aufgefordert werden.
- Wählen Sie nun das Projekt aus, das Sie in einem vorherigen Schritt erstellt haben: „flutter-firebase-codelab“.
- Als Nächstes werden Ihnen einige Fragen zur Benennung der zu generierenden Dateien gestellt. Ich empfehle, für jede Frage die Eingabetaste zu drücken, um die Standardeinstellung auszuwählen.
- Schließlich müssen Sie die Emulatoren konfigurieren. Wählen Sie Firestore und Authentication aus der Liste aus und drücken Sie dann bei jeder Frage zu den spezifischen Ports, die für die einzelnen Emulatoren verwendet werden sollen, die Eingabetaste. Wählen Sie die Standardeinstellung „Ja“ aus, wenn Sie gefragt werden, ob Sie die Emulator-Benutzeroberfläche verwenden möchten.
Am Ende des Vorgangs sollte eine Ausgabe wie im folgenden Screenshot angezeigt werden.
Wichtig: Ihre Ausgabe kann sich leicht von meiner unterscheiden, wie im Screenshot unten zu sehen ist, da die letzte Frage standardmäßig auf „Nein“ gesetzt wird, wenn Sie die Emulatoren bereits heruntergeladen haben.
FlutterFire konfigurieren
Als Nächstes können Sie mit FlutterFire den erforderlichen Dart-Code generieren, um Firebase in Ihrer Flutter-App zu verwenden.
flutterfire configure
Wenn Sie diesen Befehl ausführen, werden Sie aufgefordert, das Firebase-Projekt und die Plattformen auszuwählen, die Sie einrichten möchten. In diesem Codelab wird in den Beispielen Flutter Web verwendet. Sie können Ihr Firebase-Projekt jedoch so einrichten, dass alle Optionen verwendet werden.
Die folgenden Screenshots zeigen die Aufforderungen, die Sie beantworten müssen.
Dieser Screenshot zeigt die Ausgabe am Ende des Vorgangs. Wenn Sie mit Firebase vertraut sind, werden Sie feststellen, dass Sie keine Anwendungen in der Console erstellen mussten. Das hat die FlutterFire CLI für Sie erledigt.
Firebase-Pakete zur Flutter-App hinzufügen
Im letzten Einrichtungsschritt fügen Sie Ihrem Flutter-Projekt die relevanten Firebase-Pakete hinzu. Achten Sie im Terminal darauf, dass Sie sich im Stammverzeichnis des Flutter-Projekts unter flutter-codelabs/firebase-emulator-suite/start
befinden. Führen Sie dann die folgenden drei Befehle aus:
flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add cloud_firestore
Das sind die einzigen Pakete, die Sie in dieser Anwendung verwenden.
4. Firebase-Emulatoren aktivieren
Bisher sind die Flutter-App und Ihr Firebase-Projekt für die Verwendung der Emulatoren eingerichtet. Sie müssen dem Flutter-Code jedoch noch mitteilen, dass ausgehende Firebase-Anfragen an die lokalen Ports weitergeleitet werden sollen.
Fügen Sie zuerst den Firebase-Initialisierungscode und den Emulator-Einrichtungscode der Funktion main
in main.dart.
hinzu.
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()); }
In den ersten Zeilen des Codes wird Firebase initialisiert. Wenn Sie Firebase in einer Flutter-App verwenden, sollten Sie fast immer zuerst WidgetsFlutterBinding.ensureInitialized
und Firebase.initializeApp
aufrufen.
Danach wird mit dem Code, der mit der Zeile if (kDebugMode)
beginnt, festgelegt, dass Ihre App auf die Emulatoren und nicht auf ein Firebase-Produktionsprojekt ausgerichtet ist. kDebugMode
sorgt dafür, dass das Targeting auf die Emulatoren nur in einer Entwicklungsumgebung erfolgt. Da kDebugMode
ein konstanter Wert ist, weiß der Dart-Compiler, dass er diesen Codeblock im Release-Modus vollständig entfernen muss.
Emulatoren starten
Sie sollten die Emulatoren starten, bevor Sie die Flutter-App starten. Starten Sie die Emulatoren zuerst, indem Sie Folgendes im Terminal ausführen:
firebase emulators:start
Mit diesem Befehl werden die Emulatoren gestartet und Localhost-Ports bereitgestellt, über die wir mit ihnen interagieren können. Wenn Sie diesen Befehl ausführen, sollte die Ausgabe in etwa so aussehen:
In dieser Ausgabe sehen Sie, welche Emulatoren ausgeführt werden und wo Sie sie finden. Sehen Sie sich zuerst die Emulator-Benutzeroberfläche unter localhost:4000
an.
Dies ist die Startseite der Benutzeroberfläche des lokalen Emulators. Dort werden alle verfügbaren Emulatoren aufgelistet. Jeder Emulator ist mit dem Status „Ein“ oder „Aus“ gekennzeichnet.
5. Firebase Auth-Emulator
Der erste Emulator, den Sie verwenden, ist der Authentifizierungs-Emulator. Klicken Sie in der Benutzeroberfläche auf der Karte „Authentifizierung“ auf „Zum Emulator wechseln“, um den Auth-Emulator zu starten. Daraufhin wird eine Seite wie diese angezeigt:
Diese Seite ähnelt der Seite „Auth web console“. Sie enthält eine Tabelle mit den Nutzern wie die Onlinekonsole und ermöglicht es Ihnen, Nutzer manuell hinzuzufügen. Ein großer Unterschied besteht darin, dass in den Emulatoren nur die Authentifizierung per E‑Mail und Passwort möglich ist. Das reicht für die lokale Entwicklung aus.
Als Nächstes wird beschrieben, wie Sie dem Firebase Auth-Emulator einen Nutzer hinzufügen und sich dann über die Flutter-UI mit diesem Nutzer anmelden.
Nutzer hinzufügen
Klicken Sie auf die Schaltfläche „Nutzer hinzufügen“ und füllen Sie das Formular mit den folgenden Informationen aus:
- Anzeigename: Dash
- E-Mail: dash@email.com
- Passwort: dashword
Senden Sie das Formular ab. In der Tabelle sollte jetzt ein Nutzer enthalten sein. Jetzt können Sie den Code aktualisieren, um sich mit diesem Nutzer anzumelden.
logged_out_view.dart
Der einzige Code im LoggedOutView
-Widget, der aktualisiert werden muss, befindet sich im Callback, der ausgelöst wird, wenn ein Nutzer auf die Anmeldeschaltfläche klickt. Aktualisieren Sie den Code so:
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'), ), ), ], ), ), ); } }
Im aktualisierten Code werden die TODO
-Strings durch die E‑Mail-Adresse und das Passwort ersetzt, die Sie im Auth-Emulator erstellt haben. In der nächsten Zeile wurde die Zeile if(true)
durch Code ersetzt, der prüft, ob state.user
null ist. Der Code in AppClass
gibt Aufschluss darüber.
app_state.dart
Zwei Abschnitte des Codes in AppState
müssen aktualisiert werden. Weisen Sie dem Klassenmember „AppState.user“ zuerst den Typ User
aus dem Paket firebase_auth
anstelle des Typs Object
zu.
Füllen Sie als Nächstes die Methode AppState.login
wie unten gezeigt aus:
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!'); } } // ... }
Die Typdefinition für „user“ ist jetzt User?
. Diese User
-Klasse stammt von Firebase Auth und enthält erforderliche Informationen wie User.displayName
, die wir gleich besprechen.
Dies ist der grundlegende Code, der zum Anmelden eines Nutzers mit einer E-Mail-Adresse und einem Passwort in Firebase Auth erforderlich ist. Es wird FirebaseAuth aufgerufen, um sich anzumelden. Dabei wird ein Future<UserCredential>
-Objekt zurückgegeben. Wenn die Future abgeschlossen ist, wird mit diesem Code geprüft, ob der UserCredential
ein User
angehängt ist. Wenn im Anmeldedatenobjekt ein Nutzer vorhanden ist, hat sich ein Nutzer erfolgreich angemeldet und die AppState.user
-Eigenschaft kann festgelegt werden. Wenn nicht, ist ein Fehler aufgetreten und wird ausgegeben.
Die einzige Codezeile in dieser Methode, die spezifisch für diese App ist (und nicht allgemeiner FirebaseAuth-Code), ist der Aufruf der _listenForEntries
-Methode, die im nächsten Schritt behandelt wird.
TODO: Action Icon – Reload your app, and then press the Login button when it renders. Dadurch wird in der App eine Seite mit der Überschrift „Willkommen zurück, [Name]!“ aufgerufen. Die Authentifizierung muss funktionieren, da Sie auf diese Seite zugreifen konnten. Es muss jedoch eine kleine Aktualisierung an logged_in_view.dart
vorgenommen werden, damit der tatsächliche Name des Nutzers angezeigt wird.
logged_in_view.dart
Ändern Sie die erste Zeile in der Methode 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( // ...
In dieser Zeile wird nun die displayName
aus der User
-Property des AppState
-Objekts abgerufen. Dieser displayName
wurde im Emulator festgelegt, als Sie Ihren ersten Nutzer definiert haben. Wenn Sie sich jetzt anmelden, sollte in Ihrer App „Willkommen zurück, Dash!“ anstelle von TODO
angezeigt werden.
6. Daten in den Firestore-Emulator lesen und schreiben
Sehen Sie sich zuerst den Firestore-Emulator an. Klicken Sie auf der Startseite der Emulator-Benutzeroberfläche (localhost:4000
) auf der Firestore-Karte auf „Zum Emulator“. Das sollte so aussehen:
Emulator:
Firebase Console:
Wenn Sie bereits Erfahrung mit Firestore haben, werden Sie feststellen, dass diese Seite der Firestore-Seite in der Firebase Console ähnelt. Es gibt jedoch einige nennenswerte Unterschiede.
- Sie können alle Daten mit einem einzigen Tastendruck löschen. Das wäre bei Produktionsdaten gefährlich, ist aber für schnelle Iterationen hilfreich. Wenn Sie an einem neuen Projekt arbeiten und sich Ihr Datenmodell ändert, können Sie es ganz einfach löschen.
- Es gibt den Tab „Anfragen“. Auf diesem Tab können Sie eingehende Anfragen an diesen Emulator ansehen. Ich werde diesen Tab gleich noch genauer erläutern.
- Es gibt keine Tabs für Regeln, Indexe oder Nutzung. Es gibt ein Tool (das im nächsten Abschnitt beschrieben wird), das beim Schreiben von Sicherheitsregeln hilft. Sie können jedoch keine Sicherheitsregeln für den lokalen Emulator festlegen.
Zusammenfassend lässt sich sagen, dass diese Version von Firestore mehr Tools für die Entwicklung bietet und Tools entfernt, die in der Produktion benötigt werden.
In Firestore schreiben
Bevor wir uns den Tab „Anfragen“ im Emulator ansehen, stellen Sie zuerst eine Anfrage. Dafür sind Code-Updates erforderlich. Verbinden Sie zuerst das Formular in der App, um einen neuen Tagebucheintrag Entry
in Firestore zu schreiben.
Der allgemeine Ablauf zum Einreichen eines Entry
ist folgender:
- Nutzer hat das Formular ausgefüllt und auf die Schaltfläche
Submit
geklickt. - Die Benutzeroberfläche ruft
AppState.writeEntryToFirebase
auf. AppState.writeEntryToFirebase
fügt einen Eintrag in Firebase hinzu
Der Code in Schritt 1 oder 2 muss nicht geändert werden. Der einzige Code, der für Schritt 3 hinzugefügt werden muss, wird in der Klasse AppState
hinzugefügt. Nehmen Sie die folgende Änderung an AppState.writeEntryToFirebase
vor.
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, }); } // ... }
Der Code in der Methode „writeEntryToFirebase“ ruft eine Referenz auf die Sammlung namens „Entries“ in Firestore ab. Anschließend wird ein neuer Eintrag hinzugefügt, der vom Typ Map<String, String>
sein muss.
In diesem Fall war die Sammlung „Entries“ in Firestore nicht vorhanden, also wurde sie von Firestore erstellt.
Nachdem Sie den Code hinzugefügt haben, führen Sie einen Hot-Reload durch oder starten Sie die App neu, melden Sie sich an und rufen Sie die Ansicht EntryForm
auf. Sie können das Formular mit beliebigen Strings
ausfüllen. Das Feld „Date“ (Datum) kann einen beliebigen String enthalten, da es für dieses Codelab vereinfacht wurde. Es gibt keine starke Validierung und DateTime
-Objekte werden nicht berücksichtigt.
Klicken Sie im Formular auf „Senden“. In der App passiert nichts, aber Sie können den neuen Eintrag in der Emulator-Benutzeroberfläche sehen.
Der Tab „Anfragen“ im Firestore-Emulator
Rufen Sie in der Benutzeroberfläche den Firestore-Emulator auf und sehen Sie sich den Tab „Daten“ an. Sie sollten sehen, dass sich jetzt eine Sammlung namens „Einträge“ im Stammverzeichnis Ihrer Datenbank befindet. Dort sollte ein Dokument mit denselben Informationen zu finden sein, die Sie in das Formular eingegeben haben.
Das bestätigt, dass AppState.writeEntryToFirestore
funktioniert hat. Sie können sich die Anfrage jetzt auf dem Tab „Anfragen“ genauer ansehen. Klicken Sie jetzt auf diesen Tab.
Firestore-Emulator-Anfragen
Sie sollten eine Liste sehen, die in etwa so aussieht:
Sie können auf die einzelnen Listenelemente klicken, um viele hilfreiche Informationen aufzurufen. Klicken Sie auf das Listenelement CREATE
, das Ihrer Anfrage entspricht, um einen neuen Tagebucheintrag zu erstellen. Es wird eine neue Tabelle angezeigt, die so aussieht:
Wie bereits erwähnt, bietet der Firestore-Emulator Tools zum Entwickeln der Sicherheitsregeln Ihrer App. In dieser Ansicht sehen Sie genau, welche Zeile in Ihren Sicherheitsregeln diese Anfrage bestanden hat (oder fehlgeschlagen ist, falls das der Fall war). In einer robusteren App können Sicherheitsregeln wachsen und mehrere Autorisierungsprüfungen enthalten. Diese Ansicht hilft Ihnen, diese Autorisierungsregeln zu schreiben und zu debuggen.
Außerdem können Sie damit ganz einfach jeden Teil dieser Anfrage prüfen, einschließlich der Metadaten und der Authentifizierungsdaten. Diese Daten werden verwendet, um komplexe Autorisierungsregeln zu schreiben.
Aus Firestore lesen
Firestore synchronisiert und aktualisiert Daten auf jedem angeschlossenen Gerät. In Flutter-Code können Sie Firestore-Sammlungen und -Dokumente überwachen (oder abonnieren). Ihr Code wird jedes Mal benachrichtigt, wenn sich Daten ändern. In dieser App wird in der Methode AppState._listenForEntries
auf Firestore-Updates gewartet.
Dieser Code funktioniert in Verbindung mit den StreamController
und Stream
mit den Namen AppState._entriesStreamController
bzw. AppState.entries
. Dieser Code ist bereits geschrieben, ebenso wie der gesamte Code, der in der Benutzeroberfläche zum Anzeigen der Daten aus Firestore benötigt wird.
Aktualisieren Sie die _listenForEntries
-Methode, sodass sie dem folgenden Code entspricht:
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); }); } // ... }
Dieser Code überwacht die Sammlung „Entries“ in Firestore. Wenn Firestore diesen Client über neue Daten benachrichtigt, werden diese Daten und der Code in _listenForEntries
übergeben. Dadurch werden alle untergeordneten Dokumente in ein Objekt geändert, das von unserer App verwendet werden kann (Entry
). Anschließend werden diese Einträge dem StreamController
mit dem Namen _entriesStreamController
hinzugefügt, auf den die Benutzeroberfläche wartet. Dieser Code ist das einzige erforderliche Update.
Die Methode AppState.logIn
ruft _listenForEntries
auf, wodurch der Listening-Prozess nach der Anmeldung eines Nutzers gestartet wird.
// ... 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!'); } } // ...
Führen Sie die App nun aus. Sie sollte so aussehen:
7. Daten in den Emulator exportieren und importieren
Firebase-Emulatoren unterstützen das Importieren und Exportieren von Daten. Mit den Import- und Exportfunktionen können Sie die Entwicklung mit denselben Daten fortsetzen, wenn Sie eine Pause einlegen und dann wieder mit der Entwicklung beginnen. Sie können auch Datendateien in Git übertragen. Andere Entwickler, mit denen Sie zusammenarbeiten, haben dann Zugriff auf dieselben Daten.
Emulatordaten exportieren
Exportieren Sie zuerst die Emulatordaten, die Sie bereits haben. Öffnen Sie ein neues Terminalfenster, während die Emulatoren noch ausgeführt werden, und geben Sie den folgenden Befehl ein:
firebase emulators:export ./emulators_data
.emulators_data
ist ein Argument, das Firebase angibt, wohin die Daten exportiert werden sollen. Wenn das Verzeichnis nicht vorhanden ist, wird es erstellt. Sie können einen beliebigen Namen für dieses Verzeichnis verwenden.
Wenn Sie diesen Befehl ausführen, wird im Terminal, in dem Sie den Befehl ausgeführt haben, die folgende Ausgabe angezeigt:
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
Wenn Sie zum Terminalfenster wechseln, in dem die Emulatoren ausgeführt werden, sehen Sie diese Ausgabe:
i emulators: Received export request. Exporting data to /Users/ewindmill/Repos/codelabs/firebase-emulator-suite/complete/emulators_data. ✔ emulators: Export complete.
Wenn Sie in Ihrem Projektverzeichnis nachsehen, sollten Sie ein Verzeichnis mit dem Namen ./emulators_data
sehen, das unter anderem JSON
-Dateien mit den gespeicherten Daten enthält.
Emulatordaten importieren
Sie können diese Daten jetzt im Rahmen Ihres Entwicklungs-Workflows importieren und dort weitermachen, wo Sie aufgehört haben.
Beenden Sie zuerst die Emulatoren, falls sie ausgeführt werden, indem Sie CTRL+C
in Ihrem Terminal drücken.
Führen Sie als Nächstes den Befehl emulators:start
aus, den Sie bereits kennen, aber mit einem Flag, das angibt, welche Daten importiert werden sollen:
firebase emulators:start --import ./emulators_data
Wenn die Emulatoren aktiv sind, rufen Sie die Emulator-Benutzeroberfläche unter localhost:4000
auf. Dort sollten Sie dieselben Daten sehen, mit denen Sie zuvor gearbeitet haben.
Daten beim Schließen von Emulatoren automatisch exportieren
Sie können Daten auch automatisch exportieren lassen, wenn Sie die Emulatoren beenden. So müssen Sie nicht am Ende jeder Entwicklungssitzung daran denken, die Daten zu exportieren.
Wenn Sie Ihre Emulatoren starten, führen Sie den Befehl emulators:start
mit zwei zusätzlichen Flags aus.
firebase emulators:start --import ./emulators_data --export-on-exit
Voilà! Ihre Daten werden jetzt gespeichert und jedes Mal neu geladen, wenn Sie mit den Emulatoren für dieses Projekt arbeiten. Sie können auch ein anderes Verzeichnis als Argument für –export-on-exit flag
angeben. Standardmäßig wird jedoch das Verzeichnis verwendet, das an –import
übergeben wurde.
Sie können auch eine Kombination dieser Optionen verwenden. Hinweis aus der Dokumentation: Das Exportverzeichnis kann mit diesem Flag angegeben werden: firebase emulators:start --export-on-exit=./saved-data
. Wenn --import
verwendet wird, ist der Exportpfad standardmäßig derselbe, z. B. firebase emulators:start --import=./data-path --export-on-exit
. Übergeben Sie schließlich bei Bedarf verschiedene Verzeichnispfade an die Flags --import
und --export-on-exit
.
8. Glückwunsch!
Sie haben den Leitfaden „Erste Schritte mit dem Firebase-Emulator und Flutter“ durchgearbeitet. Den vollständigen Code für dieses Codelab finden Sie auf GitHub im Verzeichnis „complete“: Flutter Codelabs.
Behandelte Themen
- Flutter-App für die Verwendung von Firebase einrichten
- Firebase-Projekt einrichten
- FlutterFire CLI
- Firebase CLI
- Firebase Authentication-Emulator
- Firebase Firestore-Emulator
- Emulatordaten importieren und exportieren
Nächste Schritte
- Weitere Informationen zur Verwendung von Firestore und Authentication in Flutter: Codelab zu Firebase für Flutter
- Weitere Firebase-Tools mit Emulatoren:
- Cloud Storage
- Cloud Functions
- Realtime Database
- Mit FlutterFire UI können Sie Ihrer App schnell die Google-Authentifizierung hinzufügen.
Weitere Informationen
- Firebase-Website: firebase.google.com
- Flutter-Website: flutter.dev
- FlutterFire Firebase Flutter-Widgets: firebase.flutter.dev
- Firebase-YouTube-Kanal
- YouTube-Kanal von Flutter
Sparky ist stolz auf dich!