1. לפני שמתחילים
ב-codelab הזה תלמדו איך להשתמש ב-Firebase Emulator Suite עם Flutter במהלך פיתוח מקומי. תלמדו איך להשתמש באימות באמצעות אימייל וסיסמה דרך חבילת האמולטורים, ואיך לקרוא ולכתוב נתונים באמולטור של Firestore. לבסוף, תלמדו איך לייבא ולייצא נתונים מהאמולטורים, כדי שתוכלו לעבוד עם אותם נתונים מפוברקים בכל פעם שתחזרו לפיתוח.
דרישות מוקדמות
ב-codelab הזה אנחנו מניחים שיש לכם ניסיון מסוים ב-Flutter. אם לא, כדאי קודם ללמוד את היסודות. הקישורים הבאים יכולים לעזור:
- סיור במסגרת הווידג'טים של Flutter
- כדאי לנסות את שיעור ה-Lab Write Your First Flutter App, part 1
כדאי גם שיהיה לכם ניסיון מסוים ב-Firebase, אבל לא נורא אם אף פעם לא הוספתם את Firebase לפרויקט Flutter. אם אתם לא מכירים את מסוף Firebase, או אם אתם משתמשים חדשים ב-Firebase, כדאי לעיין קודם בקישורים הבאים:
מה תיצרו
בשיעור הזה תלמדו איך לפתח אפליקציה פשוטה לניהול יומן. לאפליקציה יהיה מסך כניסה ומסך שבו תוכלו לקרוא רשומות קודמות ביומן וליצור רשומות חדשות.
מה תלמדו
תלמדו איך להתחיל להשתמש ב-Firebase, ואיך לשלב את חבילת Firebase Emulator ולהשתמש בה בתהליך העבודה של פיתוח Flutter. הנושאים הבאים של Firebase יוסברו:
הערה: הנושאים האלה מכוסים במידה שהם נדרשים כדי לכסות את חבילת האמולטורים של Firebase. ה-codelab הזה מתמקד בהוספת פרויקט Firebase לאפליקציית Flutter, ובפיתוח באמצעות Firebase Emulator Suite. לא יהיו דיונים מעמיקים על Firebase Authentication או על Firestore. אם אתם לא מכירים את הנושאים האלה, מומלץ להתחיל עם המדריך Getting to Know Firebase for Flutter.
מה צריך להכין
- ידע מעשי ב-Flutter, וה-SDK מותקן
- עורכי טקסט של Intellij JetBrains או VS Code
- דפדפן Google Chrome (או יעד הפיתוח המועדף האחר שלכם ל-Flutter). חלק מהפקודות במסוף ב-codelab הזה מניחות שהאפליקציה פועלת ב-Chrome)
2. יצירה והגדרה של פרויקט Firebase
המשימה הראשונה שצריך לבצע היא יצירת פרויקט Firebase במסוף האינטרנט של Firebase. רוב התוכן של ה-codelab הזה יתמקד בחבילת הכלים לאמולטור, שמשתמשת בממשק משתמש שפועל באופן מקומי, אבל קודם צריך להגדיר פרויקט Firebase מלא.
יצירת פרויקט Firebase
- נכנסים למסוף Firebase באמצעות חשבון Google.
- לוחצים על הלחצן כדי ליצור פרויקט חדש, ואז מזינים שם לפרויקט (לדוגמה,
Firebase-Flutter-Codelab
).
- לוחצים על המשך.
- אם מוצגת בקשה לעשות זאת, קוראים ומאשרים את התנאים של Firebase, ואז לוחצים על המשך.
- (אופציונלי) מפעילים את העזרה מבוססת-AI במסוף Firebase (שנקראת Gemini ב-Firebase).
- ב-codelab הזה לא צריך להשתמש ב-Google Analytics, ולכן משביתים את האפשרות Google Analytics.
- לוחצים על יצירת פרויקט, מחכים שהפרויקט יוקצה ולוחצים על המשך.
מידע נוסף על פרויקטים ב-Firebase זמין במאמר הסבר על פרויקטים ב-Firebase.
הגדרת מוצרי Firebase
האפליקציה שאתם מפתחים משתמשת בשני מוצרי Firebase שזמינים לאפליקציות Flutter:
- אימות ב-Firebase כדי לאפשר למשתמשים להיכנס לאפליקציה.
- Cloud Firestore כדי לשמור נתונים מובנים בענן ולקבל הודעה מיידית כשמתבצעים שינויים בנתונים.
שני המוצרים האלה דורשים הגדרה מיוחדת או הפעלה באמצעות מסוף Firebase.
הפעלת Cloud Firestore
אפליקציית Flutter משתמשת ב-Cloud Firestore כדי לשמור את הרשומות ביומן.
מפעילים את Cloud Firestore:
- בקטע Build במסוף Firebase, לוחצים על Cloud Firestore.
- לוחצים על יצירת מסד נתונים.
- בוחרים באפשרות הפעלה במצב בדיקה. קוראים את כתב הוויתור לגבי כללי האבטחה. מצב הבדיקה מאפשר לכם לכתוב למסד הנתונים באופן חופשי במהלך הפיתוח. לוחצים על הבא.
- בוחרים את המיקום של מסד הנתונים (אפשר להשתמש בברירת המחדל). חשוב לדעת: אי אפשר לשנות את המיקום הזה בשלב מאוחר יותר.
- לוחצים על Enable.
3. הגדרת אפליקציית Flutter
לפני שמתחילים, צריך להוריד את קוד ההתחלה ולהתקין את Firebase CLI.
קבלת קוד לתחילת הדרך
משכפלים את המאגר ב-GitHub משורת הפקודה:
git clone https://github.com/flutter/codelabs.git flutter-codelabs
לחלופין, אם מותקן אצלכם הכלי GitHub's cli:
gh repo clone flutter/codelabs flutter-codelabs
צריך לשכפל את הקוד לדוגמה לספרייה flutter-codelabs
, שמכילה את הקוד של אוסף של סדנאות קוד. הקוד של ה-Codelab הזה נמצא ב-flutter-codelabs/firebase-emulator-suite
.
מבנה הספריות מתחת ל-flutter-codelabs/firebase-emulator-suite
מורכב משני פרויקטים של Flutter. אחד מהם נקרא complete
, ואפשר להשתמש בו אם רוצים לדלג קדימה או להשוות אותו לקוד שלכם. הפרויקט השני נקרא start
.
הקוד שרוצים להתחיל איתו נמצא בספרייה flutter-codelabs/firebase-emulator-suite/start
. פותחים את הספרייה או מייבאים אותה לסביבת הפיתוח המשולבת (IDE) המועדפת.
cd flutter-codelabs/firebase-emulator-suite/start
התקנת Firebase CLI
ממשק Firebase CLI מספק כלים לניהול פרויקטים ב-Firebase. כדי להשתמש ב-Emulator Suite, צריך להתקין את ה-CLI.
יש כמה דרכים להתקין את ה-CLI. אם משתמשים ב-MacOS או ב-Linux, הדרך הכי פשוטה היא להריץ את הפקודה הזו מהטרמינל:
curl -sL https://firebase.tools | bash
אחרי שמתקינים את ה-CLI, צריך לבצע אימות ב-Firebase.
- מריצים את הפקודה הבאה כדי להתחבר ל-Firebase באמצעות חשבון Google:
firebase login
- הפקודה הזו מקשרת את המחשב המקומי ל-Firebase ומעניקה לכם גישה לפרויקטים של Firebase.
- כדי לבדוק שה-CLI מותקן בצורה תקינה ושיש לו גישה לחשבון שלכם, מריצים את הפקודה לרשימת הפרויקטים ב-Firebase. מריצים את הפקודה הבאה:
firebase projects:list
- הרשימה שמוצגת צריכה להיות זהה לרשימת הפרויקטים ב-Firebase שמופיעה במסוף Firebase. צריך לראות לפחות את firebase-flutter-codelab.
התקנת FlutterFire CLI
ממשק FlutterFire CLI מבוסס על Firebase CLI, והוא מאפשר לשלב פרויקט Firebase באפליקציית Flutter בקלות רבה יותר.
קודם כול, מתקינים את ה-CLI:
dart pub global activate flutterfire_cli
מוודאים שה-CLI הותקן. מריצים את הפקודה הבאה בספריית הפרויקט של Flutter ומוודאים שתפריט העזרה מוצג ב-CLI.
flutterfire --help
שימוש ב-Firebase CLI וב-FlutterFire CLI כדי להוסיף את פרויקט Firebase לאפליקציית Flutter
אחרי שמתקינים את שני ממשקי ה-CLI, אפשר להגדיר מוצרים ספציפיים של Firebase (כמו Firestore), להוריד את האמולטורים ולהוסיף את Firebase לאפליקציית Flutter באמצעות כמה פקודות במסוף.
קודם כול, צריך להריץ את הפקודה הבאה כדי לסיים את ההגדרה של Firebase:
firebase init
הפקודה הזו תציג לכם סדרה של שאלות שנדרשות להגדרת הפרויקט. צילומי המסך הבאים מציגים את התהליך:
- כשמתבקשים לבחור תכונות, בוחרים באפשרות Firestore ובאפשרות Emulators. (אין אפשרות אימות, כי לא נעשה שימוש בהגדרה שאפשר לשנות מקובצי הפרויקט של Flutter).
- בשלב הבא, כשמוצגת הנחיה, בוחרים באפשרות 'שימוש בפרויקט קיים'.
- עכשיו בוחרים את הפרויקט שיצרתם בשלב הקודם: flutter-firebase-codelab.
- בשלב הבא תתבקשו לענות על כמה שאלות לגבי מתן שמות לקבצים שייווצרו. אני מציעה ללחוץ על Enter לכל שאלה כדי לבחור את ברירת המחדל.
- לבסוף, צריך להגדיר את האמולטורים. בוחרים באפשרות Firestore ובאפשרות Authentication (אימות) מהרשימה, ואז מקישים על Enter לכל שאלה לגבי היציאות הספציפיות שבהן רוצים להשתמש לכל אמולטור. כשנשאלים אם רוצים להשתמש בממשק המשתמש של האמולטור, צריך לבחור באפשרות ברירת המחדל, 'כן'.
בסיום התהליך, אמור להופיע פלט שדומה לזה שמופיע בצילום המסך הבא.
חשוב: יכול להיות שהפלט שלכם יהיה שונה מעט מהפלט שלי, כמו שרואים בצילום המסך שלמטה, כי אם כבר הורדתם את האמולטורים, התשובה לשאלה האחרונה תהיה 'לא' כברירת מחדל.
הגדרת FlutterFire
לאחר מכן, תוכלו להשתמש ב-FlutterFire כדי ליצור את קוד Dart שנדרש לשימוש ב-Firebase באפליקציית Flutter.
flutterfire configure
כשמריצים את הפקודה הזו, מוצגת בקשה לבחור את פרויקט Firebase שרוצים להשתמש בו ואת הפלטפורמות שרוצים להגדיר. ב-codelab הזה, הדוגמאות משתמשות ב-Flutter Web, אבל אתם יכולים להגדיר את פרויקט Firebase כך שישתמש בכל האפשרויות.
בצילומי המסך הבאים מוצגות ההנחיות שצריך לענות עליהן.
בצילום המסך הזה מוצג הפלט בסוף התהליך. אם אתם מכירים את Firebase, תשימו לב שלא הייתם צריכים ליצור אפליקציות במסוף, ו-FlutterFire CLI עשה את זה בשבילכם.
הוספת חבילות Firebase לאפליקציית Flutter
בשלב האחרון בהגדרה מוסיפים את חבילות Firebase הרלוונטיות לפרויקט Flutter. במסוף, מוודאים שאתם נמצאים בתיקיית הבסיס של פרויקט Flutter בנתיב flutter-codelabs/firebase-emulator-suite/start
. לאחר מכן, מריצים את שלוש הפקודות הבאות:
flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add cloud_firestore
אלה החבילות היחידות שתשתמשו בהן באפליקציה הזו.
4. הפעלת אמולטורים של Firebase
עד עכשיו, אפליקציית Flutter ופרויקט Firebase מוגדרים כך שאפשר להשתמש באמולטורים, אבל עדיין צריך להגדיר בקוד Flutter להפנות מחדש בקשות יוצאות של Firebase ליציאות המקומיות.
קודם מוסיפים את קוד האתחול של Firebase ואת קוד ההגדרה של האמולטור לפונקציה main
בקובץ 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()); }
בשורה הראשונה של הקוד מתבצעת הפעלה של Firebase. ברוב המקרים, אם אתם עובדים עם Firebase באפליקציית Flutter, כדאי להתחיל בקריאה ל-WidgetsFlutterBinding.ensureInitialized
ול-Firebase.initializeApp
.
אחרי כן, הקוד שמתחיל בשורה if (kDebugMode)
אומר לאפליקציה לטרגט את האמולטורים ולא פרויקט Firebase בייצור. kDebugMode
מוודא שהטירגוט של האמולטורים יתבצע רק אם אתם בסביבת פיתוח. מכיוון ש-kDebugMode
הוא ערך קבוע, קומפיילר Dart יודע להסיר את בלוק הקוד הזה לחלוטין במצב הפצה.
הפעלת האמולטורים
צריך להפעיל את האמולטורים לפני שמפעילים את אפליקציית Flutter. כדי להפעיל את האמולטורים, מריצים את הפקודה הבאה במסוף:
firebase emulators:start
הפקודה הזו מפעילה את האמולטורים וחושפת יציאות של localhost שאפשר ליצור איתן אינטראקציה. כשמריצים את הפקודה, הפלט אמור להיראות כך:
הפלט הזה מראה אילו אמולטורים פועלים, ואיפה אפשר לראות את האמולטורים. קודם כול, כדאי לעיין בממשק המשתמש של האמולטור בכתובת localhost:4000
.
זהו דף הבית של ממשק המשתמש של האמולטור המקומי. מוצגת רשימה של כל האמולטורים הזמינים, ולכל אחד מהם יש תווית עם הסטטוס שלו: מופעל או מושבת.
5. האמולטור של Firebase Auth
האמולטור הראשון שתשתמשו בו הוא אמולטור האימות. כדי להתחיל להשתמש באמולטור האימות, לוחצים על 'מעבר לאמולטור' בכרטיס האימות בממשק המשתמש. יוצג דף שנראה כך:
הדף הזה דומה לדף של מסוף האינטרנט של אימות. הוא כולל טבלה עם רשימת המשתמשים, כמו במסוף אונליין, ומאפשר להוסיף משתמשים באופן ידני. הבדל גדול אחד הוא ששיטת האימות היחידה שזמינה באמולטורים היא באמצעות אימייל וסיסמה. זה מספיק לפיתוח מקומי.
בשלב הבא, נסביר איך להוסיף משתמש לאמולטור של Firebase Auth, ואז להתחבר באמצעות ממשק המשתמש של Flutter.
הוספת משתמש
לוחצים על הלחצן 'הוספת משתמש' וממלאים את הטופס בפרטים הבאים:
- השם המוצג: Dash
- אימייל: dash@email.com
- סיסמה: dashword
שולחים את הטופס ורואים שהטבלה כוללת עכשיו משתמש. עכשיו אפשר לעדכן את הקוד כדי להתחבר באמצעות המשתמש הזה.
logged_out_view.dart
הקוד היחיד בווידג'ט LoggedOutView
שצריך לעדכן הוא בפונקציית הקריאה החוזרת שמופעלת כשמשתמש לוחץ על לחצן הכניסה. מעדכנים את הקוד כך שייראה כמו הקוד הבא:
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'), ), ), ], ), ), ); } }
הקוד המעודכן מחליף את המחרוזות TODO
בכתובת האימייל ובסיסמה שיצרתם באמולטור האימות. ובשורה הבאה, השורה if(true)
הוחלפה בקוד שבודק אם state.user
הוא null. הקוד ב-AppClass
מספק מידע נוסף על הנושא.
app_state.dart
צריך לעדכן שני חלקים בקוד ב-AppState
. קודם כל, צריך לתת למשתנה AppState.user של חבר הכיתה את הסוג User
מהחבילה firebase_auth
, ולא את הסוג Object
.
בשלב השני, ממלאים את המתודה AppState.login
כמו שמוצג בהמשך:
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!'); } } // ... }
הגדרת הסוג של המשתמש היא עכשיו User?
. המחלקות User
מגיעות מ-Firebase Auth ומספקות מידע נדרש כמו User.displayName
, שנדון בו בהמשך.
זהו קוד בסיסי שנדרש כדי להכניס משתמש באמצעות כתובת אימייל וסיסמה ב-Firebase Auth. הפונקציה מבצעת קריאה ל-FirebaseAuth כדי להיכנס לחשבון, והיא מחזירה אובייקט Future<UserCredential>
. כשהעתיד מסתיים, הקוד הזה בודק אם יש User
שמצורף ל-UserCredential
. אם יש משתמש באובייקט של פרטי הכניסה, סימן שהמשתמש התחבר בהצלחה, ואפשר להגדיר את המאפיין AppState.user
. אם לא, הייתה שגיאה והיא מודפסת.
שימו לב שהשורה היחידה בקוד של השיטה הזו שספציפית לאפליקציה הזו (ולא קוד כללי של FirebaseAuth) היא הקריאה לשיטה _listenForEntries
, שנסביר עליה בשלב הבא.
TODO: Action Icon – Reload your app, and then press the Login button when it renders. הפעולה הזו גורמת לאפליקציה לנווט לדף שמופיע בו הכיתוב 'ברוך שובך, שם!' בחלק העליון. האימות פועל, כי הוא אפשר לך לעבור לדף הזה, אבל צריך לבצע עדכון קל ב-logged_in_view.dart
כדי להציג את השם האמיתי של המשתמש.
logged_in_view.dart
משנים את השורה הראשונה בשיטה 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( // ...
עכשיו, השורה הזו מאחזרת את displayName
מהמאפיין User
באובייקט AppState
. הערך displayName
הוגדר באמולטור כשציינתם את המשתמש הראשון. עכשיו, כשמתחברים לאפליקציה, מוצגת ההודעה "ברוך שובך, דאש!" במקום TODO
.
6. קריאה וכתיבה של נתונים באמולטור Firestore
קודם כול, כדאי לעיין באמולטור של Firestore. בדף הבית של ממשק המשתמש של האמולטור (localhost:4000
), לוחצים על 'מעבר לאמולטור' בכרטיס Firestore. הוא אמור להיראות כך:
אמולטור:
מסוף Firebase:
אם יש לכם ניסיון ב-Firestore, תשימו לב שהדף הזה דומה לדף Firestore במסוף Firebase. עם זאת, יש כמה הבדלים חשובים.
- אפשר לנקות את כל הנתונים בלחיצה על כפתור אחד. הפעולה הזו עלולה להיות מסוכנת עם נתוני ייצור, אבל היא שימושית לביצוע איטרציות מהירות. אם אתם עובדים על פרויקט חדש ומודל הנתונים משתנה, קל לנקות את הנתונים.
- יש כרטיסייה בשם 'בקשות'. בכרטיסייה הזו אפשר לצפות בבקשות נכנסות שמוגשות לאמולטור הזה. בהמשך נסביר על הכרטיסייה הזו בצורה מפורטת יותר.
- אין כרטיסיות של כללים, אינדקסים או שימוש. יש כלי (שמוסבר בקטע הבא) שעוזר לכתוב כללי אבטחה, אבל אי אפשר להגדיר כללי אבטחה לאמולטור המקומי.
לסיכום, הגרסה הזו של Firestore מספקת יותר כלים שימושיים במהלך הפיתוח, ומסירה כלים שנדרשים בייצור.
כתיבה ל-Firestore
לפני שנדון בכרטיסייה 'בקשות' באמולטור, צריך קודם לשלוח בקשה. לשם כך נדרשים עדכוני קוד. מתחילים בחיבור הטופס באפליקציה כדי לכתוב יומן חדש Entry
ל-Firestore.
התהליך הכללי לשליחת Entry
הוא:
- המשתמש מילא את הטופס ולחץ על הלחצן
Submit
- ממשק המשתמש נקרא
AppState.writeEntryToFirebase
AppState.writeEntryToFirebase
מוסיף רשומה ל-Firebase
אין צורך לשנות את הקוד שמופיע בשלב 1 או בשלב 2. הקוד היחיד שצריך להוסיף לשלב 3 יתווסף בכיתה AppState
. צריך לבצע את השינוי הבא ב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, }); } // ... }
הקוד בשיטה writeEntryToFirebase מאחזר הפניה לאוסף שנקרא Entries ב-Firestore. לאחר מכן נוספת רשומה חדשה, שצריכה להיות מסוג Map<String, String>
.
במקרה הזה, האוסף Entries ב-Firestore לא היה קיים, ולכן Firestore יצר אותו.
אחרי שמוסיפים את הקוד, מבצעים טעינה מחדש או מפעילים מחדש את האפליקציה, מתחברים ועוברים לתצוגה EntryForm
. אתם יכולים למלא את הטופס בכל Strings
שתרצו. (השדה Date (תאריך) יקבל כל מחרוזת, כי הוא פשוט יותר ב-codelab הזה. אין לה אימות חזק או שהיא לא מתייחסת לאובייקטים של DateTime
בשום צורה).
לוחצים על 'שליחה' בטופס. לא יקרה כלום באפליקציה, אבל תוכלו לראות את הרשומה החדשה בממשק המשתמש של האמולטור.
הכרטיסייה Requests (בקשות) באמולטור Firestore
בממשק המשתמש, עוברים אל אמולטור Firestore ומסתכלים בכרטיסייה 'נתונים'. עכשיו אמור להופיע אוסף בשם 'Entries' בבסיס הנתונים. צריך להיות לך מסמך עם אותו מידע שהזנת בטופס.
האישור הזה מעיד על כך שהפעולה AppState.writeEntryToFirestore
הצליחה, ועכשיו אפשר לבדוק את הבקשה בכרטיסייה 'בקשות'. לוחצים על הכרטיסייה.
בקשות לאמולטור Firestore
כאן אמורה להופיע רשימה שדומה לזו:
אפשר ללחוץ על כל אחד מהפריטים ברשימה כדי לראות מידע מועיל. לוחצים על הפריט CREATE
ברשימה שמתאים לבקשה ליצירת רשומה חדשה ביומן. תוצג טבלה חדשה שנראית כך:
כמו שצוין, האמולטור של Firestore מספק כלים לפיתוח כללי האבטחה של האפליקציה. בתצוגה הזו אפשר לראות בדיוק באיזו שורה בכללי האבטחה הבקשה הזו עברה (או נכשלה, אם זה המקרה). באפליקציה חזקה יותר, כללי האבטחה יכולים לגדול ולכלול מספר בדיקות הרשאה. התצוגה הזו עוזרת לכתוב ולנפות באגים בכללי ההרשאה האלה.
בנוסף, היא מאפשרת לבדוק בקלות כל חלק בבקשה הזו, כולל המטא-נתונים ונתוני האימות. הנתונים האלה משמשים לכתיבת כללי הרשאה מורכבים.
קריאה מ-Firestore
Firestore משתמש בסנכרון נתונים כדי לשלוח נתונים מעודכנים למכשירים מחוברים. בקוד Flutter, אפשר להאזין (או להירשם) לאוספים ולמסמכים של Firestore, והקוד יקבל הודעה בכל פעם שיהיו שינויים בנתונים. באפליקציה הזו, ההאזנה לעדכונים של Firestore מתבצעת בשיטה שנקראת AppState._listenForEntries
.
הקוד הזה פועל בשילוב עם StreamController
ו-Stream
שנקראים AppState._entriesStreamController
ו-AppState.entries
, בהתאמה. הקוד הזה כבר כתוב, כמו כל הקוד שנדרש בממשק המשתמש כדי להציג את הנתונים מ-Firestore.
מעדכנים את השיטה _listenForEntries
כך שתהיה זהה לקוד שבהמשך:
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); }); } // ... }
הקוד הזה מאזין לאוסף Entries ב-Firestore. כש-Firestore מודיע ללקוח שיש נתונים חדשים, הוא מעביר את הנתונים האלה ואת הקוד ב-_listenForEntries
משנה את כל מסמכי הצאצא שלו לאובייקט שהאפליקציה שלנו יכולה להשתמש בו (Entry
). לאחר מכן, הוא מוסיף את הרשומות האלה ל-StreamController
שנקרא _entriesStreamController
(שממשק המשתמש מאזין לו). הקוד הזה הוא העדכון היחיד שנדרש.
לבסוף, כדאי לזכור שהשיטה AppState.logIn
מבצעת קריאה אל _listenForEntries
, שמתחילה את תהליך ההאזנה אחרי שהמשתמש מתחבר.
// ... 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!'); } } // ...
עכשיו מריצים את האפליקציה. היא אמורה להיראות כך:
7. ייצוא וייבוא של נתונים לאמולטור
האמולטורים של Firebase תומכים בייבוא וייצוא של נתונים. השימוש בייבוא ובייצוא מאפשר לכם להמשיך בפיתוח עם אותם נתונים כשאתם לוקחים הפסקה מהפיתוח ואז חוזרים אליו. אפשר גם לבצע קומיט של קובצי נתונים ב-git, ומפתחים אחרים שעובדים איתכם יוכלו לעבוד עם אותם נתונים.
ייצוא נתונים מהאמולטור
קודם מייצאים את נתוני האמולטור שכבר יש לכם. בזמן שהאמולטורים עדיין פועלים, פותחים חלון טרמינל חדש ומזינים את הפקודה הבאה:
firebase emulators:export ./emulators_data
.emulators_data
הוא ארגומנט שמציין ל-Firebase לאן לייצא את הנתונים. אם הספרייה לא קיימת, היא נוצרת. אתם יכולים להשתמש בכל שם שתרצו לספרייה הזו.
כשמריצים את הפקודה הזו, הפלט הבא מוצג במסוף שבו הפקודה הופעלה:
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
אם תעברו לחלון הטרמינל שבו פועלים האמולטורים, תראו את הפלט הבא:
i emulators: Received export request. Exporting data to /Users/ewindmill/Repos/codelabs/firebase-emulator-suite/complete/emulators_data. ✔ emulators: Export complete.
ולסיום, אם תבדקו בספריית הפרויקט, תראו ספרייה בשם ./emulators_data
, שמכילה קובצי JSON
, בין קובצי מטא-נתונים אחרים, עם הנתונים ששמרתם.
ייבוא נתונים של אמולטור
עכשיו אפשר לייבא את הנתונים האלה כחלק מתהליך העבודה של הפיתוח, ולהמשיך מהמקום שבו הפסקתם.
קודם צריך לעצור את האמולטורים אם הם פועלים. לשם כך, לוחצים על CTRL+C
במסוף.
לאחר מכן, מריצים את הפקודה emulators:start
שכבר ראיתם, אבל עם דגל שמציין אילו נתונים לייבא:
firebase emulators:start --import ./emulators_data
כשהאמולטורים יופעלו, עוברים לממשק המשתמש של האמולטור בכתובת localhost:4000
, ויוצגו אותם הנתונים שעבדתם איתם קודם.
ייצוא נתונים אוטומטי כשסוגרים אמולטורים
אפשר גם לייצא נתונים באופן אוטומטי כשיוצאים מהאמולטורים, במקום לזכור לייצא את הנתונים בסוף כל סשן פיתוח.
כשמפעילים את האמולטורים, מריצים את הפקודה emulators:start
עם שני דגלים נוספים.
firebase emulators:start --import ./emulators_data --export-on-exit
Voila! הנתונים יישמרו וייטענו מחדש בכל פעם שתעבדו עם האמולטורים בפרויקט הזה. אפשר גם לציין ספרייה אחרת כארגומנט ל-–export-on-exit flag
, אבל ברירת המחדל היא הספרייה שמועברת ל-–import
.
אפשר גם להשתמש בכל שילוב של האפשרויות האלה. זו הערה ממאמרי העזרה: אפשר לציין את ספריית הייצוא באמצעות הדגל הזה: firebase emulators:start --export-on-exit=./saved-data
. אם משתמשים בדגל --import
, נתיב הייצוא יהיה זהה כברירת מחדל. לדוגמה: firebase emulators:start --import=./data-path --export-on-exit
. לבסוף, אם רוצים, מעבירים נתיבי ספריות שונים לסימנים --import
ו---export-on-exit
.
8. כל הכבוד!
סיימתם את המאמר 'התחלת העבודה עם כלי האמולטור של Firebase ו-Flutter'. אפשר למצוא את הקוד המלא של ה-Codelab הזה בספרייה complete ב-GitHub: Flutter Codelabs
מה נכלל
- הגדרת אפליקציית Flutter לשימוש ב-Firebase
- הגדרת פרויקט Firebase
- FlutterFire CLI
- Firebase CLI
- אמולטור של אימות ב-Firebase
- אמולטור Firebase Firestore
- ייבוא וייצוא של נתונים מהאמולטור
השלבים הבאים
- מידע נוסף על שימוש ב-Firestore ובאימות ב-Flutter: הדרכה בנושא Firebase ל-Flutter
- כדאי לעיין בכלי Firebase אחרים שמציעים אמולטורים:
- Cloud Storage
- Cloud Functions
- מסד נתונים בזמן אמת
- כדאי לעיין ב-FlutterFire UI כדי להוסיף במהירות אימות של Google לאפליקציה.
מידע נוסף
- אתר Firebase: firebase.google.com
- אתר Flutter: flutter.dev
- FlutterFire Firebase Flutter widgets: firebase.flutter.dev
- ערוץ YouTube של Firebase
- ערוץ YouTube של Flutter
ספארקי גאה בך!