大家好!在 Day 9,我們成功地解決了跨頁面狀態管理的問題,App 的核心流程已基本完成。但我們也面臨一個新挑戰:所有資料在 App 關閉後就跟著煙消雲散。為了讓「省錢拍拍」成為一個真正可用的產品,我們需要一個強大、可靠的後端來永久保存資料。
今天,我們將迎來本系列最重大的里程碑之一:正式引入後端服務。我們將使用 Google 旗下的 Firebase 作為我們的後端大腦。本篇的目標是:
這一步是未來所有雲端功能的基石,讓我們開始吧!
snapsaver-app
。接著按照提示完成建立流程(可以暫時關閉 Google Analytics)。firebase login
,它會引導你透過瀏覽器登入 Google 帳號。dart pub global activate flutterfire_cli
執行這段程式碼後會顯示,意思是 flutterfire
工具已經安裝成功了,它被放在以下資料夾中,複製這行路徑並加入到 Windows 的環境變數 Path
中,最後將 VS Code 整個重啟。
Warning: Pub installs executables into C:\xxxx\xxxx\AppData\Local\Pub\Cache\bin, which is not on your path.
關於 Path 環境變數的警告,這是 Windows 用戶較常遇到的情況。macOS/Linux 用戶的路徑可能不同
4. 自動設定:在專案根目錄下,執行 flutterfire configure
。CLI 會自動偵測你 Firebase 帳號下的專案,選擇我們剛剛建立的 snapsaver-app
,並選擇你要支援的平台 (例如 Android, iOS)。它會自動為你完成所有平台的註冊。
新增依賴的方法:
方法一、
打開 pubspec.yaml
,加入 firebase_core
(核心) 與 firebase_auth
(驗證) 這兩個套件。
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
# ... 其他套件 ...
firebase_core: ^2.32.0 # 請使用最新版本
firebase_auth: ^4.20.0 # 請使用最新版本
儲存檔案並執行 flutter pub get。
方法二、
輸入指令,會自動抓取最新穩定版並加入 pubspec.yaml。
flutter pub add firebase_core firebase_auth
main
函式中初始化 Firebase:這是啟動 App 前必須完成的關鍵步驟。我們需要修改 main
函式,讓它變成 async
,並在 runApp
之前初始化 Firebase。// lib/main.dart
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart'; // 導入 Core
import 'package:snapsaver/firebase_options.dart'; // 導入自動生成的設定檔
// ...
Future<void> main() async {
// 確保 Flutter Engine 已經初始化
WidgetsFlutterBinding.ensureInitialized();
// 初始化 Firebase
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
現在,我們需要一個讓使用者輸入帳號密碼的頁面。為了簡化流程,我們將註冊和登入功能放在同一個頁面。
建立一個新的 auth_page.dart
檔案,並在 main.dart
中將 MyApp
的 home
指向它。
// lib/auth_page.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class AuthPage extends StatefulWidget {
const AuthPage({super.key});
@override
State<AuthPage> createState() => _AuthPageState();
}
class _AuthPageState extends State<AuthPage> {
// 為 TextField 建立控制器,以便取得使用者輸入的內容
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
// 建立一個 GlobalKey 給 Scaffold,方便顯示 SnackBar
final _scaffoldKey = GlobalKey<ScaffoldState>();
// [最佳實踐] 記得在 State 銷毀時 dispose 控制器,以釋放資源
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
// 顯示提示訊息的輔助函式
void _showSnackBar(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message)),
);
}
Future<void> _signUp() async {
try {
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
// [優化] 提供明確的 UI 回饋,而不是只用 print
_showSnackBar('註冊成功!');
// 註冊成功後的操作,例如跳轉頁面...
} on FirebaseAuthException catch (e) {
// 處理常見錯誤
final message = e.code == 'email-already-in-use'
? '此 Email 已被註冊'
: '註冊失敗: ${e.message}';
_showSnackBar(message);
}
}
Future<void> _signIn() async {
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
_showSnackBar('登入成功!');
// 登入成功後的操作...
} on FirebaseAuthException catch (e) {
// 處理常見錯誤
final message = e.code == 'user-not-found' || e.code == 'wrong-password'
? 'Email 或密碼錯誤'
: '登入失敗: ${e.message}';
_showSnackBar(message);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey, // 綁定 GlobalKey
appBar: AppBar(title: const Text('登入 / 註冊')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'Email')),
TextField(
controller: _passwordController,
decoration: const InputDecoration(labelText: '密碼'),
obscureText: true),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(onPressed: _signIn, child: const Text('登入')),
ElevatedButton(onPressed: _signUp, child: const Text('註冊')),
],
)
],
),
),
);
}
}
現在,運行你的 App,你就可以透過這個頁面,在 Firebase 後台的 Authentication 頁面中看到新註冊的使用者了!
今天我們邁出了一大步,成功地將 Firebase 這個強大的後端整合進了我們的 App。我們學會了:
firebase_auth
套件的 API 來實現基本的 Email/密碼註冊與登入。我們現在有「使用者」了!但這些使用者還沒有地方可以存放他們自己的資料。
明天,我們將基於今天的使用者系統,開始規劃 Firestore 雲端資料庫的結構,設計一個既高效又能保護使用者隱私的資料模型,為儲存每個人的消費紀錄做準備。