1. ก่อนเริ่มต้น
ใน Codelab นี้ คุณจะได้เรียนรู้วิธีใช้ชุดโปรแกรมจำลอง Firebase กับ Flutter ระหว่างการพัฒนาในเครื่อง คุณจะได้ดูวิธีใช้การตรวจสอบสิทธิ์อีเมลด้วยรหัสผ่านผ่านชุดโปรแกรมจำลอง และวิธีอ่านและเขียนข้อมูลลงในโปรแกรมจำลอง Firestore สุดท้าย ให้ใช้การนำเข้าและส่งออกข้อมูลจากโปรแกรมจำลอง เพื่อทำงานกับข้อมูลปลอมเดียวกันทุกครั้งที่กลับไปที่การพัฒนาซอฟต์แวร์
ข้อกำหนดเบื้องต้น
Codelab นี้จะสมมติว่าคุณมีประสบการณ์การใช้งาน Flutter อยู่บ้าง หากไม่ คุณอาจต้องเรียนรู้ข้อมูลเบื้องต้นก่อน ลิงก์ต่อไปนี้มีประโยชน์
- ชมทัวร์ชมเฟรมเวิร์กวิดเจ็ต Flutter
- ลองใช้ Codelab ของ Write Your First Flutter App ตอนที่ 1
คุณควรมีประสบการณ์การใช้งาน Firebase อยู่บ้าง แต่ไม่เคยเพิ่ม Firebase ในโปรเจ็กต์ Flutter เลย หากคุณไม่คุ้นเคยกับคอนโซล Firebase หรือเพิ่งเริ่มใช้ Firebase เลย โปรดดูลิงก์ต่อไปนี้ก่อน
สิ่งที่คุณจะสร้าง
Codelab นี้จะแนะนำคุณตลอดการสร้างแอปพลิเคชันรายการบันทึกที่ใช้งานง่าย แอปพลิเคชันจะมีหน้าจอการเข้าสู่ระบบและหน้าจอที่ช่วยให้คุณอ่านรายการบันทึกที่ผ่านมา และสร้างรายการใหม่ได้
สิ่งที่คุณจะได้เรียนรู้
คุณจะได้ดูวิธีเริ่มใช้ Firebase รวมถึงวิธีผสานรวมและใช้ชุดโปรแกรมจำลอง Firebase ในเวิร์กโฟลว์การพัฒนา Flutter เราจะกล่าวถึงหัวข้อ Firebase ต่อไปนี้
โปรดทราบว่าหัวข้อเหล่านี้จะครอบคลุมเท่าที่จำเป็นต้องครอบคลุมชุดโปรแกรมจำลอง Firebase Codelab นี้มุ่งเน้นที่การเพิ่มโปรเจ็กต์ Firebase ลงในแอป Flutter และการพัฒนาโดยใช้ Firebase Emulator Suite จะไม่มีการพูดคุยเชิงลึกเกี่ยวกับการตรวจสอบสิทธิ์ Firebase หรือ Firestore หากคุณไม่คุ้นเคยกับหัวข้อเหล่านี้ เราขอแนะนำให้เริ่มต้นด้วยหัวข้อทำความรู้จัก Firebase สำหรับ Flutter Codelab
สิ่งที่ต้องมี
- ความรู้ในการใช้งาน Flutter และติดตั้ง SDK
- Intellij JetBrains หรือตัวแก้ไขข้อความ VS Code
- เบราว์เซอร์ Google Chrome (หรือเป้าหมายการพัฒนาอื่นๆ ที่ต้องการสำหรับ Flutter คำสั่งเทอร์มินัลบางคำสั่งใน Codelab จะถือว่าคุณกำลังเรียกใช้แอปใน Chrome)
2. สร้างและตั้งค่าโปรเจ็กต์ Firebase
งานแรกที่คุณต้องทำให้เสร็จคือสร้างโปรเจ็กต์ Firebase ในเว็บคอนโซลของ Firebase Codelab ส่วนใหญ่นี้จะมุ่งเน้นที่ชุดโปรแกรมจำลอง ซึ่งใช้ UI ที่ทำงานภายในเครื่อง แต่คุณต้องตั้งค่าโปรเจ็กต์ Firebase ที่สมบูรณ์ก่อน
สร้างโปรเจ็กต์ Firebase
- ลงชื่อเข้าใช้คอนโซล Firebase
- ในคอนโซล Firebase ให้คลิกเพิ่มโปรเจ็กต์ (หรือสร้างโปรเจ็กต์) แล้วป้อนชื่อโปรเจ็กต์ Firebase (เช่น "Firebase-Flutter-Codelab")
- คลิกตัวเลือกการสร้างโปรเจ็กต์ ยอมรับข้อกำหนดของ Firebase หากได้รับข้อความแจ้ง ข้ามการตั้งค่า Google Analytics เนื่องจากคุณจะไม่ใช้ Analytics สําหรับแอปนี้
ดูข้อมูลเพิ่มเติมเกี่ยวกับโปรเจ็กต์ Firebase ได้ที่ทำความเข้าใจโปรเจ็กต์ Firebase
แอปที่คุณกำลังสร้างใช้ผลิตภัณฑ์ Firebase 2 รายการที่พร้อมใช้งานสำหรับแอป Flutter ดังนี้
- การตรวจสอบสิทธิ์ของ Firebase เพื่ออนุญาตให้ผู้ใช้ลงชื่อเข้าใช้แอปได้
- Cloud Firestore เพื่อบันทึก Structured Data ในระบบคลาวด์และรับการแจ้งเตือนทันทีเมื่อข้อมูลมีการเปลี่ยนแปลง
ผลิตภัณฑ์ทั้ง 2 รายการนี้ต้องมีการกำหนดค่าพิเศษหรือต้องเปิดใช้โดยใช้คอนโซล Firebase
เปิดใช้ Cloud Firestore
แอป Flutter ใช้ Cloud Firestore เพื่อบันทึกรายการบันทึก
เปิดใช้ Cloud Firestore
- ในส่วนสร้างของคอนโซล Firebase ให้คลิก Cloud Firestore
- คลิกสร้างฐานข้อมูล
- เลือกตัวเลือกเริ่มในโหมดทดสอบ อ่านข้อจำกัดความรับผิดเกี่ยวกับกฎความปลอดภัย โหมดทดสอบช่วยให้คุณเขียนไปยังฐานข้อมูลได้อย่างอิสระในระหว่างการพัฒนา คลิกถัดไป
- เลือกตำแหน่งสำหรับฐานข้อมูล (คุณสามารถใช้ค่าเริ่มต้นได้) โปรดทราบว่าตำแหน่งนี้เปลี่ยนแปลงในภายหลังไม่ได้
- คลิกเปิดใช้
3. ตั้งค่าแอป Flutter
คุณจะต้องดาวน์โหลดโค้ดเริ่มต้น และติดตั้ง Firebase CLI ก่อนที่เราจะเริ่มต้น
รับรหัสเริ่มต้น
โคลนที่เก็บ GitHub จากบรรทัดคำสั่งดังนี้
git clone https://github.com/flutter/codelabs.git flutter-codelabs
หรือหากคุณติดตั้งเครื่องมือ cli ของ GitHub ไว้ ให้ทำดังนี้
gh repo clone flutter/codelabs flutter-codelabs
ควรโคลนโค้ดตัวอย่างลงในไดเรกทอรี flutter-codelabs
ซึ่งมีโค้ดสำหรับคอลเล็กชัน Codelab โค้ดสำหรับ Codelab นี้คือ flutter-codelabs/firebase-emulator-suite
โครงสร้างไดเรกทอรีภายใต้ flutter-codelabs/firebase-emulator-suite
ประกอบด้วยโปรเจ็กต์ Flutter 2 โปรเจ็กต์ โค้ดแรกเรียกว่า complete
ซึ่งคุณจะดูได้หากต้องการข้ามหรืออ้างอิงโค้ดของคุณเอง อีกโปรเจ็กต์หนึ่งมีชื่อว่า start
รหัสที่คุณต้องการใช้เริ่มต้นอยู่ในไดเรกทอรี flutter-codelabs/firebase-emulator-suite/start
เปิดหรือนำเข้าไดเรกทอรีนั้นไปยัง IDE ที่ต้องการ
cd flutter-codelabs/firebase-emulator-suite/start
ติดตั้ง Firebase CLI
Firebase CLI มีเครื่องมือสำหรับการจัดการโปรเจ็กต์ Firebase ต้องมี CLI เพื่อใช้ชุดโปรแกรมจำลอง คุณจึงต้องติดตั้ง 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 ทั้ง 2 รายการแล้ว คุณสามารถตั้งค่าผลิตภัณฑ์ Firebase แต่ละรายการ (เช่น Firestore) ดาวน์โหลดโปรแกรมจำลอง และเพิ่ม Firebase ไปยังแอป Flutter ได้ด้วยคำสั่งเทอร์มินัลเพียง 2-3 คำสั่ง
ก่อนอื่น ให้ตั้งค่า Firebase ให้เสร็จโดยการเรียกใช้โค้ดต่อไปนี้
firebase init
คำสั่งนี้จะนำคุณไปยังชุดคำถามที่ต้องใช้ในการสร้างโปรเจ็กต์ ภาพหน้าจอต่อไปนี้จะแสดงขั้นตอน
- เมื่อมีข้อความแจ้งให้เลือกฟีเจอร์ ให้เลือก "Firestore" และ "โปรแกรมจำลอง" (ไม่มีตัวเลือกการตรวจสอบสิทธิ์ เนื่องจากไม่ได้ใช้การกำหนดค่าที่แก้ไขได้จากไฟล์โปรเจ็กต์ Flutter)
- ถัดไป ให้เลือก "ใช้โปรเจ็กต์ที่มีอยู่" เมื่อมีข้อความแจ้ง
- ต่อไปให้เลือกโปรเจ็กต์ที่คุณสร้างในขั้นตอนก่อนหน้า: flutter-firebase-codelab
- จากนั้น เราจะถามคำถามชุดหนึ่งเกี่ยวกับการตั้งชื่อไฟล์ที่จะสร้างขึ้น ฉันขอแนะนำให้กด "Enter" สำหรับแต่ละคำถามเพื่อเลือกค่าเริ่มต้น
- และสุดท้าย คุณจะต้องกำหนดค่าโปรแกรมจำลอง เลือก Firestore และการตรวจสอบสิทธิ์จากรายการ แล้วกด "Enter" สำหรับคำถามแต่ละข้อเกี่ยวกับพอร์ตที่จะใช้สำหรับโปรแกรมจำลองแต่ละตัว คุณควรเลือกค่าเริ่มต้นเป็น ใช่ เมื่อระบบถามว่าคุณต้องการใช้ UI โปรแกรมจำลองหรือไม่
ในตอนท้ายของกระบวนการ คุณควรเห็นผลลัพธ์ที่คล้ายกับภาพหน้าจอต่อไปนี้
สำคัญ: ผลลัพธ์ของคุณอาจแตกต่างไปจากนี้เล็กน้อยตามที่แสดงในภาพหน้าจอด้านล่าง เนื่องจากคำถามสุดท้ายจะมีค่าเริ่มต้นเป็น "ไม่" หากคุณดาวน์โหลดโปรแกรมจำลองไว้แล้ว
กำหนดค่า 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
จากนั้นเรียกใช้คำสั่ง 3 คำสั่งต่อไปนี้
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()); }
โค้ด 2-3 บรรทัดแรกจะเริ่มต้น Firebase หากคุณใช้งาน Firebase ในแอป Flutter อยู่เกือบทั้งหมด คุณจะต้องเริ่มต้นด้วยการโทรหา WidgetsFlutterBinding.ensureInitialized
และ Firebase.initializeApp
หลังจากนั้น โค้ดที่ขึ้นต้นด้วยบรรทัด if (kDebugMode)
จะบอกแอปของคุณให้กำหนดเป้าหมายโปรแกรมจำลองแทนโปรเจ็กต์ Firebase ที่ใช้งานจริง kDebugMode
ช่วยให้มั่นใจว่าการกำหนดเป้าหมายโปรแกรมจำลองจะเกิดขึ้นเฉพาะเมื่ออยู่ในสภาพแวดล้อมการพัฒนาซอฟต์แวร์เท่านั้น เนื่องจาก kDebugMode
เป็นค่าคงที่ คอมไพเลอร์ของ Dart จะรู้ว่าต้องนำโค้ดบล็อกดังกล่าวออกทั้งหมดในโหมดเผยแพร่
เริ่มต้นโปรแกรมจำลอง
คุณควรเริ่มโปรแกรมจำลองก่อนเริ่มแอป Flutter ก่อนอื่น ให้เริ่มต้นโปรแกรมจำลองโดยการเรียกใช้โปรแกรมในเทอร์มินัล
firebase emulators:start
คำสั่งนี้จะเปิดเครื่องจำลองให้เริ่มทำงาน และแสดงพอร์ต localhost ที่เราสามารถโต้ตอบด้วยได้ เมื่อเรียกใช้คำสั่งดังกล่าว คุณควรเห็นเอาต์พุตในลักษณะนี้
เอาต์พุตนี้จะบอกคุณว่าโปรแกรมจำลองใดทำงานอยู่ และสามารถดูโปรแกรมจำลองได้จากที่ใด ขั้นแรก โปรดดู UI โปรแกรมจำลองที่ localhost:4000
นี่คือหน้าแรกของ UI ของโปรแกรมจำลองในเครื่อง ซึ่งจะแสดงรายการโปรแกรมจำลองทั้งหมดที่มี และแต่ละโปรแกรมจะมีป้ายกำกับสถานะเป็นเปิดหรือปิด
5. โปรแกรมจำลองการตรวจสอบสิทธิ์ Firebase
โปรแกรมจำลองแรกที่คุณจะใช้คือโปรแกรมจำลองการตรวจสอบสิทธิ์ เริ่มด้วยโปรแกรมจำลองการตรวจสอบสิทธิ์โดยคลิก "ไปที่โปรแกรมจำลอง" บนการ์ดการตรวจสอบสิทธิ์ใน UI และคุณจะเห็นหน้าเว็บดังนี้
หน้านี้มีความคล้ายคลึงกับหน้าเว็บคอนโซลการตรวจสอบสิทธิ์ โดยมีตารางแสดงรายการผู้ใช้ เช่น คอนโซลออนไลน์ และอนุญาตให้คุณเพิ่มผู้ใช้ด้วยตนเอง ความแตกต่างที่สำคัญอย่างหนึ่งคือ ตัวเลือกวิธีการตรวจสอบสิทธิ์เดียวที่มีอยู่ในโปรแกรมจำลองคือผ่านอีเมลและรหัสผ่าน ซึ่งเพียงพอสำหรับการพัฒนาในท้องถิ่น
ต่อไปเป็นขั้นตอนการเพิ่มผู้ใช้ลงในโปรแกรมจำลองการตรวจสอบสิทธิ์ Firebase จากนั้นจึงเข้าสู่ระบบให้ผู้ใช้ดังกล่าวผ่าน UI ของ Flutter
เพิ่มผู้ใช้
คลิก "เพิ่มผู้ใช้" แล้วกรอกแบบฟอร์มพร้อมข้อมูลต่อไปนี้
- ชื่อที่แสดง: ขีดกลาง
- อีเมล: dash@email.com
- รหัสผ่าน: เครื่องหมายขีดกลาง
ส่งแบบฟอร์ม แล้วคุณจะเห็นตารางที่มีผู้ใช้ ตอนนี้คุณจะอัปเดตโค้ดเพื่อเข้าสู่ระบบด้วยผู้ใช้รายนั้นได้
loggle_out_view.dart
รหัสเดียวในวิดเจ็ต LoggedOutView
ที่ต้องอัปเดตจะอยู่ใน Callback ที่ทริกเกอร์เมื่อผู้ใช้กดปุ่มเข้าสู่ระบบ อัปเดตโค้ดให้มีลักษณะดังนี้
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
เป็นค่าว่างหรือไม่ โค้ดใน AppClass
ช่วยให้เข้าใจเรื่องนี้มากขึ้น
app_state.dart
ต้องอัปเดตโค้ด 2 ส่วนใน AppState
ขั้นแรก ให้สมาชิกคลาส AppState.user ประเภท User
จากแพ็กเกจ firebase_auth
แทนประเภท Object
ขั้นที่ 2 กรอกเมธอด 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
ซึ่งจะกล่าวถึงในขั้นตอนถัดไป
สิ่งที่ต้องทำ: ไอคอนการทำงาน – โหลดแอปของคุณซ้ำ แล้วกดปุ่มเข้าสู่ระบบเมื่อแสดงผล ซึ่งจะทำให้แอปไปยังหน้าที่ระบุว่า "ยินดีต้อนรับกลับมานะ คน!" ที่ด้านบน การตรวจสอบสิทธิ์นั้นต้องได้ผลเพราะอนุญาตให้คุณไปที่หน้านี้ได้ แต่จำเป็นต้องอัปเดต logged_in_view.dart
เล็กน้อยเพื่อให้แสดงชื่อจริงของผู้ใช้ได้
loggle_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
นี้ในโปรแกรมจำลองเมื่อคุณกำหนดผู้ใช้รายแรก ตอนนี้แอปของคุณควรแสดง "ยินดีต้อนรับกลับมานะ Dash!" เมื่อคุณลงชื่อเข้าสู่ระบบ แทนที่จะเป็น TODO
6. อ่านและเขียนข้อมูลไปยังโปรแกรมจำลอง Firestore
ขั้นแรก ลองดูโปรแกรมจำลอง Firestore ในหน้าแรกของ UI โปรแกรมจำลอง (localhost:4000
) ให้คลิก "ไปที่โปรแกรมจำลอง" ในการ์ด Firestore ซึ่งควรมีลักษณะดังนี้
โปรแกรมจำลอง:
คอนโซล Firebase
หากคุณเคยใช้ Firestore คุณจะพบว่าหน้านี้ดูคล้ายกับหน้า Firestore ในคอนโซล Firebase แต่ก็มีข้อแตกต่างที่สำคัญอยู่บ้าง
- คุณสามารถล้างข้อมูลทั้งหมดได้โดยแตะเพียงปุ่มเดียว กระบวนการนี้อาจเป็นอันตรายต่อข้อมูลการผลิต แต่ก็มีประโยชน์สําหรับการทำซ้ำอย่างรวดเร็ว หากคุณกำลังทำงานในโปรเจ็กต์ใหม่และรูปแบบข้อมูลมีการเปลี่ยนแปลง คุณสามารถล้างออกได้
- มี "คำขอ" แท็บนี้ช่วยให้คุณดูคำขอที่เข้ามาใหม่ซึ่งส่งไปยังโปรแกรมจำลองนี้ได้ เราจะพูดถึงแท็บนี้อย่างละเอียดยิ่งขึ้นในอีกสักครู่
- ไม่มีแท็บสำหรับกฎ ดัชนี หรือการใช้งาน มีเครื่องมือ (ที่จะอธิบายในส่วนถัดไป) ที่ช่วยในการเขียนกฎความปลอดภัย แต่คุณตั้งกฎความปลอดภัยสำหรับโปรแกรมจำลองในเครื่องไม่ได้
สรุปง่ายๆ ก็คือ Firestore เวอร์ชันนี้มีเครื่องมือที่เป็นประโยชน์มากกว่าในระหว่างการพัฒนา รวมทั้งนำเครื่องมือที่ต้องมีในเวอร์ชันที่ใช้งานจริงออกด้วย
เขียนไปยัง Firestore
ก่อนกล่าวถึง "คำขอ" ในโปรแกรมจำลอง ให้ส่งคำขอก่อน การดำเนินการนี้ต้องมีการอัปเดตโค้ด เริ่มต้นด้วยการต่อแบบฟอร์มในแอปเพื่อเขียนบันทึกประจำวันใหม่ Entry
ไปยัง Firestore
ขั้นตอนระดับสูงในการส่ง Entry
มีดังนี้
- ผู้ใช้กรอกแบบฟอร์มและกดปุ่ม
Submit
- UI เรียกใช้
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>
ในกรณีนี้ "รายการ" ไม่มีคอลเล็กชันใน Firestore จึงสร้างคอลเล็กชันขึ้น
เมื่อเพิ่มโค้ดแล้ว ให้ Hot โหลดซ้ำหรือรีสตาร์ทแอป ลงชื่อเข้าสู่ระบบ และไปที่มุมมองEntryForm
คุณสามารถกรอกข้อมูลในแบบฟอร์มด้วย Strings
ได้ตามต้องการ (ฟิลด์วันที่จะใช้สตริงใดก็ได้ เนื่องจากโค้ดแล็บนี้เรียบง่ายขึ้น เนื่องจากไม่มีการตรวจสอบที่หนักแน่นหรือให้ความสำคัญกับออบเจ็กต์ DateTime
แต่อย่างใด)
กดส่งในแบบฟอร์ม จะไม่มีสิ่งใดเกิดขึ้นในแอป แต่คุณสามารถดูรายการใหม่ได้ใน UI ของโปรแกรมจำลอง
แท็บคำขอในโปรแกรมจำลอง Firestore
ใน UI ให้ไปที่โปรแกรมจำลอง Firestore แล้วดูที่ "ข้อมูล" คุณจะเห็นว่าตอนนี้มีคอลเล็กชันที่รูทของฐานข้อมูลชื่อ "รายการ" ซึ่งควรมีเอกสารที่มีข้อมูลตรงกับที่คุณป้อนลงในแบบฟอร์ม
ข้อความนี้ยืนยันว่า AppState.writeEntryToFirestore
ใช้งานได้แล้ว และขณะนี้คุณสามารถดูคำขอเพิ่มเติมได้ในแท็บคำขอ คลิกแท็บนั้นทันที
คำขอโปรแกรมจำลอง Firestore
ที่นี่คุณจะเห็นรายการที่คล้ายกับตัวอย่างนี้
คุณสามารถคลิกเข้าไปในรายการใดก็ได้เพื่อดูข้อมูลที่เป็นประโยชน์มากมาย คลิกที่รายการ CREATE
ที่ตรงกับคำขอของคุณในการสร้างรายการบันทึกใหม่ คุณจะเห็นตารางใหม่ที่มีลักษณะดังนี้
ตามที่กล่าวไว้ โปรแกรมจำลอง Firestore มีเครื่องมือในการพัฒนากฎความปลอดภัยของแอป มุมมองนี้จะแสดงบรรทัดในกฎความปลอดภัยที่คำขอนี้ผ่าน (หรือล้มเหลวหากเป็นกรณีดังกล่าว) ในแอปที่มีประสิทธิภาพมากขึ้น กฎความปลอดภัยสามารถขยายตัวได้และต้องมีการตรวจสอบการให้สิทธิ์หลายรายการ มุมมองนี้ใช้เพื่อช่วยเขียนและแก้ไขข้อบกพร่องของกฎการให้สิทธิ์เหล่านั้น
นอกจากนี้ ยังเป็นวิธีง่ายๆ ในการตรวจสอบคำขอทุกรายการนี้ ซึ่งรวมถึงข้อมูลเมตาและข้อมูลการตรวจสอบสิทธิ์ ระบบจะใช้ข้อมูลนี้เพื่อเขียนกฎการให้สิทธิ์ที่ซับซ้อน
กำลังอ่านจาก Firestore
Firestore ใช้การซิงค์ข้อมูลเพื่อพุชข้อมูลที่อัปเดตไปยังอุปกรณ์ที่เชื่อมต่อ โดยคุณจะฟัง (หรือสมัครใช้บริการ) คอลเล็กชันและเอกสารของ Firestore ได้ในโค้ด Flutter และโค้ดจะได้รับการแจ้งเตือนทุกครั้งที่ข้อมูลมีการเปลี่ยนแปลง ในแอปนี้ ระบบจะฟังการอัปเดต Firestore ในเมธอด AppState._listenForEntries
โค้ดนี้จะทำงานร่วมกับ StreamController
และ Stream
ที่เรียกว่า AppState._entriesStreamController
และ AppState.entries
ตามลำดับ เราเขียนโค้ดดังกล่าวไว้แล้ว เช่นเดียวกับโค้ดทั้งหมดที่ต้องมีใน UI เพื่อแสดงข้อมูลจาก 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); }); } // ... }
โค้ดนี้จะรับคำสั่ง "รายการ" ใน Firestore เมื่อ Firestore แจ้งไคลเอ็นต์นี้ว่ามีข้อมูลใหม่ ระบบจะส่งผ่านข้อมูลดังกล่าวและโค้ดใน _listenForEntries
จะเปลี่ยนเอกสารย่อยทั้งหมดเป็นออบเจ็กต์ที่แอปใช้ได้ (Entry
) จากนั้นจะเพิ่มรายการเหล่านี้ลงใน StreamController
ที่ชื่อว่า _entriesStreamController
(ซึ่ง UI กำลังฟังอยู่) รหัสนี้เป็นรหัสเดียวที่ต้องอัปเดต
สุดท้าย อย่าลืมว่าเมธอด 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
เมื่อโปรแกรมจำลองทำงานแล้ว ให้ไปที่ UI โปรแกรมจำลองที่ localhost:4000
แล้วคุณจะเห็นข้อมูลเดียวกันกับที่เคยใช้ก่อนหน้านี้
ส่งออกข้อมูลโดยอัตโนมัติเมื่อปิดโปรแกรมจำลอง
นอกจากนี้คุณยังส่งออกข้อมูลโดยอัตโนมัติเมื่อปิดโปรแกรมจำลองได้ แทนที่จะจำว่าต้องส่งออกข้อมูลเมื่อสิ้นสุดเซสชันการพัฒนาทุกเซสชัน
เมื่อคุณเริ่มโปรแกรมจำลอง ให้เรียกใช้คำสั่ง emulators:start
พร้อมด้วยแฟล็กเพิ่มเติม 2 รายการ
firebase emulators:start --import ./emulators_data --export-on-exit
เสร็จแล้ว! ตอนนี้ข้อมูลของคุณจะได้รับการบันทึกและโหลดซ้ำทุกครั้งที่คุณทำงานกับโปรแกรมจำลองสำหรับโปรเจ็กต์นี้ คุณยังระบุไดเรกทอรีอื่นเป็นอาร์กิวเมนต์ของ –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 ได้ใน "เสร็จสมบูรณ์" ไดเรกทอรีใน GitHub: Flutter Codelabs
สรุปประเด็นที่ได้พูดถึง
- การตั้งค่าแอป Flutter เพื่อใช้ Firebase
- การสร้างโปรเจ็กต์ Firebase
- CLI สำหรับ FlutterFire
- Firebase CLI
- โปรแกรมจำลองการตรวจสอบสิทธิ์ Firebase
- โปรแกรมจำลอง Firebase Firestore
- การนำเข้าและส่งออกข้อมูลโปรแกรมจำลอง
ขั้นตอนถัดไป
- ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Firestore และการตรวจสอบสิทธิ์ใน Flutter: ทำความรู้จัก Firebase สำหรับ Flutter Codelab
- สำรวจเครื่องมือ Firebase อื่นๆ ที่มีโปรแกรมจำลอง
- พื้นที่เก็บข้อมูลระบบคลาวด์
- ฟังก์ชันระบบคลาวด์
- ฐานข้อมูลเรียลไทม์
- สำรวจ FlutterFire UI เพื่อเพิ่มการตรวจสอบสิทธิ์ของ Google ลงในแอปอย่างรวดเร็ว
ดูข้อมูลเพิ่มเติม
- เว็บไซต์ Firebase: firebase.google.com
- เว็บไซต์ Flutter: flutter.dev
- วิดเจ็ต Firebase Flutter ของ FlutterFire: firebase.flutter.dev
- ช่อง YouTube ของ Firebase
- ช่อง YouTube ของ Flutter
Sparky ภูมิใจในตัวคุณ