iT邦幫忙

2025 iThome 鐵人賽

DAY 10
0
自我挑戰組

攜手 AI 從零開始打造一款 Flutter 應用程式系列 第 10

Day 10: 引入後端大腦 - Firebase 專案設定與使用者驗證

  • 分享至 

  • xImage
  •  

前言

大家好!在 Day 9,我們成功地解決了跨頁面狀態管理的問題,App 的核心流程已基本完成。但我們也面臨一個新挑戰:所有資料在 App 關閉後就跟著煙消雲散。為了讓「省錢拍拍」成為一個真正可用的產品,我們需要一個強大、可靠的後端來永久保存資料。

今天,我們將迎來本系列最重大的里程碑之一:正式引入後端服務。我們將使用 Google 旗下的 Firebase 作為我們的後端大腦。本篇的目標是:

  1. 從零開始建立一個 Firebase 專案。
  2. 為我們的 Flutter App 完成 Firebase 的基礎設定。
  3. 整合 Firebase Authentication (驗證) 服務,為 App 加上使用者註冊與登入功能。

這一步是未來所有雲端功能的基石,讓我們開始吧!

Step 1: 建立你的第一個 Firebase 專案

  1. 前往 Firebase 控制台:打開瀏覽器,前往 Firebase Console,並使用你的 Google 帳號登入。
  2. 新增專案:點擊「新增專案」,為專案命名,這裡我們取名為 snapsaver-app。接著按照提示完成建立流程(可以暫時關閉 Google Analytics)。
  3. 啟用驗證服務:進入專案儀表板後,在左側導航欄點擊「建構」>「Authentication」。接著,點擊「開始使用」,在登入服務供應商列表中,選擇「電子郵件/密碼」,並將其「啟用」,然後儲存。

Step 2: 將 Firebase 連接到你的 Flutter App

  1. 安裝 Firebase CLI:Firebase 命令列介面 (CLI) 是最現代、最方便的整合工具。請參考官方文件安裝 Firebase CLI。
  2. 登入 Firebase:安裝完成後,在你的終端機中執行 firebase login,它會引導你透過瀏覽器登入 Google 帳號。
  3. 安裝 FlutterFire CLI:回到你的 Flutter 專案終端機,執行以下指令來安裝 FlutterFire CLI:
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 用戶的路徑可能不同

Path
4. 自動設定:在專案根目錄下,執行 flutterfire configure。CLI 會自動偵測你 Firebase 帳號下的專案,選擇我們剛剛建立的 snapsaver-app,並選擇你要支援的平台 (例如 Android, iOS)。它會自動為你完成所有平台的註冊。

Step 3: 在 App 中加入 Firebase 套件並初始化

新增依賴的方法:

方法一、
打開 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
  1. 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());
}

Step 4: 打造登入/註冊頁面

現在,我們需要一個讓使用者輸入帳號密碼的頁面。為了簡化流程,我們將註冊和登入功能放在同一個頁面。

建立一個新的 auth_page.dart 檔案,並在 main.dart 中將 MyApphome 指向它。

// 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。我們學會了:

  1. 建立 Firebase 專案並啟用驗證服務。
  2. 使用 FlutterFire CLI 自動化設定流程。
  3. 在 App 啟動時正確地初始化 Firebase。
  4. 呼叫 firebase_auth 套件的 API 來實現基本的 Email/密碼註冊與登入。

我們現在有「使用者」了!但這些使用者還沒有地方可以存放他們自己的資料。

明天,我們將基於今天的使用者系統,開始規劃 Firestore 雲端資料庫的結構,設計一個既高效又能保護使用者隱私的資料模型,為儲存每個人的消費紀錄做準備。


上一篇
Day 9: 讓資料「回家」- 跨頁面狀態管理入門
下一篇
Day 11: 為資料找個家 - Firestore 雲端資料庫結構設計
系列文
攜手 AI 從零開始打造一款 Flutter 應用程式12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言