Flutter: Firebase 集成

Firebase 是 Flutter 的超级助手——Auth、数据库、存储、分析、推送,五合一开箱即用。

📋 前置知识:需要先掌握以下内容

1. 你将学到


2. 一个自建后端崩溃的真实故事

(1) 痛点:自建后端运维成本高

Bob 的 ShopApp 自建后端用 Node.js + PostgreSQL + S3,运维 3 人团队,月成本 20 thousand USD。一次数据库迁移导致 4 小时宕机,损失 50 thousand USD 订单。实时商品库存同步需要 WebSocket,自建方案复杂且不稳定。推送通知用第三方服务,经常延迟。

(2) Firebase 全家桶的解法

Firebase 提供了 Auth + Firestore + Storage + Analytics + FCM 一站式后端,无需运维服务器,实时数据自动同步。

DART
import 'package:cloud_firestore/cloud_firestore.dart';

// ⚙️ **安装依赖**:flutter pub add cloud_firestore

// 自定义类定义来源:
// - Product: 见第11课 json_serializable 模型(需添加 fromFirestore 工厂构造函数)

// Firestore real-time product updates
FirebaseFirestore.instance
  .collection('products')
  .where('stock', isGreaterThan: 0)
  .snapshots()
  .listen((snapshot) {
    // UI auto-updates when stock changes
    products = snapshot.docs.map((d) => Product.fromFirestore(d)).toList();
  });
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

(3) 收益:零运维 + 实时同步 + 成本减半

Bob 迁移到 Firebase 后,后端运维团队缩减 2 人,月成本从 20 thousand USD 降到 8 thousand USD,实时数据延迟从秒级降到毫秒级。


3. Firebase 架构全景

100%
graph TD
    FB[Firebase] --> AUTH[Authentication]
    FB --> FS[Cloud Firestore]
    FB --> ST[Cloud Storage]
    FB --> AN[Analytics]
    FB --> CM[Cloud Messaging]
    FS --> |snapshots| PL[ProductList Realtime]
    AUTH --> |authStateChanges| LP[LoginPage]
    CM --> |onMessage| NP[NotificationPopup]
    AN --> |logEvent| DA[Dashboard Analytics]
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

(1) Firebase 服务矩阵

服务 用途 定价
Authentication 用户认证 免费额度大
Cloud Firestore NoSQL 实时数据库 免费额度:50K 读/天
Cloud Storage 文件存储 免费额度:5GB
Analytics 用户行为分析 免费
Cloud Messaging 推送通知 免费
Crashlytics 崩溃上报 免费

4. Firebase 项目配置

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

:FlutterFire 初始化

BASH
# Install FlutterFire CLI
dart pub global activate flutterfire_cli

# Configure Firebase project
flutterfire configure

# Add dependencies
flutter pub add firebase_core firebase_auth cloud_firestore firebase_storage firebase_analytics firebase_messaging
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。
DART
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

// ⚙️ **安装依赖**:flutter pub add firebase_core
// ⚙️ **项目配置**:dart pub global activate flutterfire_cli && flutterfire configure

// lib/main.dart
import 'firebase_options.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  runApp(const ShopApp());
}
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

5. Authentication

(1) 登录方式对比

方式 复杂度 用户体验 适用场景
Email/Password 通用
Google Sign-In Android 首选
Apple Sign-In iOS 必需
匿名登录 高(无感) 先体验后注册
手机号验证 验证身份

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

:AuthService 封装

DART
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

// ⚙️ **安装依赖**:flutter pub add firebase_auth google_sign_in

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  Stream<User?> get authStateChanges => _auth.authStateChanges();

  Future<UserCredential> signInWithEmail(String email, String password) =>
      _auth.signInWithEmailAndPassword(email: email, password: password);

  Future<UserCredential> signUpWithEmail(String email, String password) =>
      _auth.createUserWithEmailAndPassword(email: email, password: password);

  Future<UserCredential> signInWithGoogle() async {
    final googleUser = await GoogleSignIn().signIn();
    final googleAuth = await googleUser?.authentication;
    final credential = GoogleAuthProvider.credential(
      accessToken: googleAuth?.accessToken,
      idToken: googleAuth?.idToken,
    );
    return _auth.signInWithCredential(credential);
  }

  Future<UserCredential> signInAnonymously() => _auth.signInAnonymously();

  Future<void> signOut() => _auth.signOut();

  User? get currentUser => _auth.currentUser;
}
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

:Riverpod Auth Notifier + Firebase

DART
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

// ⚙️ **安装依赖**:flutter pub add firebase_auth flutter_riverpod riverpod_annotation
// ⚙️ **开发依赖**:flutter pub add --dev riverpod_generator build_runner

// 自定义类定义来源:
// - AuthService: 见本课第5节 AuthService 封装

@riverpod
class FirebaseAuth extends _$FirebaseAuth {
  @override
  AsyncValue<User?> build() {
    final service = AuthService();
    // Listen to auth state changes
    service.authStateChanges.listen((user) {
      state = AsyncData(user);
    });
    return AsyncData(service.currentUser);
  }

  Future<void> login(String email, String password) async {
    state = const AsyncLoading();
    state = await AsyncValue.guard(() => AuthService().signInWithEmail(email, password));
  }

  Future<void> loginWithGoogle() async {
    state = const AsyncLoading();
    state = await AsyncValue.guard(() => AuthService().signInWithGoogle());
  }

  Future<void> logout() async {
    await AuthService().signOut();
  }
}
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

6. Cloud Firestore

(1) 数据建模

TEXT 📖 仅展示
firestore/
├── products/{productId}
│   ├── name: "Pro Laptop"
│   ├── price: 1299.99
│   ├── stock: 150
│   ├── category: "Electronics"
│   └── imageUrl: "gs://shopapp.appspot.com/products/laptop.jpg"
├── users/{userId}
│   ├── name: "Bob"
│   ├── email: "alice@shopapp.com"
│   ├── addresses: [{...}]
│   └── preferences: {theme: "dark", currency: "USD"}
├── orders/{orderId}
│   ├── userId: "alice_123"
│   ├── items: [{productId, quantity, price}]
│   ├── total: 99.99
│   ├── status: "shipped"
│   └── createdAt: Timestamp
└── reviews/{reviewId}
    ├── productId: "laptop_001"
    ├── userId: "bob_456"
    ├── rating: 4.5
    └── comment: "Great product!"
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

:Firestore CRUD

DART
import 'package:cloud_firestore/cloud_firestore.dart';

// ⚙️ **安装依赖**:flutter pub add cloud_firestore

// 自定义类定义来源:
// - Product: 见第11课 json_serializable 模型(需添加 fromFirestore 工厂构造函数)

class ProductFirestore {
  final _db = FirebaseFirestore.instance;

  Future<List<Product>> getProducts({String? category, int limit = 20}) async {
    Query query = _db.collection('products').orderBy('rating', descending: true).limit(limit);
    if (category != null) query = query.where('category', isEqualTo: category);
    final snapshot = await query.get();
    return snapshot.docs.map((d) => Product.fromFirestore(d)).toList();
  }

  Future<Product> getProduct(String id) async {
    final doc = await _db.collection('products').doc(id).get();
    return Product.fromFirestore(doc);
  }

  // Real-time listener
  Stream<List<Product>> watchProducts({String? category}) {
    Query query = _db.collection('products').where('stock', isGreaterThan: 0);
    if (category != null) query = query.where('category', isEqualTo: category);
    return query.snapshots().map((s) => s.docs.map((d) => Product.fromFirestore(d)).toList());
  }

  Future<void> updateStock(String productId, int newStock) =>
      _db.collection('products').doc(productId).update({'stock': newStock});
}
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

:Firestore 安全规则

JAVASCRIPT
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Products: anyone can read, only admins can write
    match /products/{productId} {
      allow read: if true;
      allow write: if isAdmin();
    }
    // Orders: users can read/write own orders
    match /orders/{orderId} {
      allow read, write: if request.auth != null && request.auth.uid == resource.data.userId;
      allow create: if request.auth != null;
    }
    // Reviews: anyone can read, authenticated users can create
    match /reviews/{reviewId} {
      allow read: if true;
      allow create: if request.auth != null;
    }
  }
}
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

7. Cloud Storage

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

:商品图片上传与下载

DART
import 'package:firebase_storage/firebase_storage.dart';
import 'dart:io';

// ⚙️ **安装依赖**:flutter pub add firebase_storage

class StorageService {
  final _storage = FirebaseStorage.instance;

  Future<String> uploadProductImage(String filePath, String productId) async {
    final ref = _storage.ref().child('products/$productId/${DateTime.now().millisecondsSinceEpoch}.jpg');
    final uploadTask = ref.putFile(File(filePath));
    final snapshot = await uploadTask;
    return await snapshot.ref.getDownloadURL();
  }

  Future<String> getDownloadUrl(String path) =>
      _storage.ref().child(path).getDownloadURL();

  // Upload with progress
  Stream<double> uploadWithProgress(String filePath, String productId) {
    final ref = _storage.ref().child('products/$productId/main.jpg');
    return ref.putFile(File(filePath)).snapshotEvents.map((s) {
      return s.bytesTransferred / s.totalBytes;
    });
  }
}
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

8. Analytics + Cloud Messaging

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

:Analytics 埋点

DART
import 'package:firebase_analytics/firebase_analytics.dart';

// ⚙️ **安装依赖**:flutter pub add firebase_analytics

// 自定义类定义来源:
// - Product: 见第11课 json_serializable 模型
// - Order: 见第14课 Order 模型

class ShopAnalytics {
  static final _analytics = FirebaseAnalytics.instance;

  static Future<void> logViewProduct(Product product) =>
      _analytics.logEvent(name: 'view_product', parameters: {
        'product_id': product.id,
        'product_name': product.name,
        'price': product.price,
        'category': product.category,
      });

  static Future<void> logAddToCart(Product product, int quantity) =>
      _analytics.logEvent(name: 'add_to_cart', parameters: {
        'product_id': product.id,
        'quantity': quantity,
        'price': product.price,
        'currency': 'USD',
      });

  static Future<void> logPurchase(Order order) =>
      _analytics.logEvent(name: 'purchase', parameters: {
        'order_id': order.id,
        'value': order.total,
        'currency': 'USD',
        'item_count': order.items.length,
      });

  static Future<void> setUserProperty(String name, String value) =>
      _analytics.setUserProperty(name: name, value: value);
}
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

:FCM 推送通知

DART
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';

// ⚙️ **安装依赖**:flutter pub add firebase_messaging

class NotificationService {
  static final _messaging = FirebaseMessaging.instance;

  static Future<void> init() async {
    // Request permission
    await _messaging.requestPermission();

    // Get FCM token
    final token = await _messaging.getToken();
    debugPrint('FCM Token: $token');

    // Foreground messages
    FirebaseMessaging.onMessage.listen((message) {
      debugPrint('Foreground message: ${message.notification?.title}');
    });

    // Background messages
    FirebaseMessaging.onMessageOpenedApp.listen((message) {
      // Handle notification tap
      final productId = message.data['product_id'];
      if (productId != null) {
        // Navigate to product detail
      }
    });
  }
}
TEXT 📖 仅展示
> **输出:** 在本地 Flutter SDK(Flutter 3.x / Dart 3.x)运行。Piston 服务器未安装 Flutter,请在本机 `flutter run` 实操对照。实际 UI/状态会因平台略有差异。

❓ 常见问题

Q Firebase 免费额度够用吗?
A Firestore 免费 50K 读/20K 写/天,小规模应用足够。百万级 DAU 需要付费方案。
Q Firestore 和 Realtime Database 怎么选?
A 新项目用 Firestore(更强大的查询、更好的数据模型)。Realtime Database 仅适合需要极低延迟的实时场景。
Q Firebase Auth 的 Token 怎么和后端 API 集成?
Aawait user.getIdToken() 获取 JWT,传给后端验证。后端用 Firebase Admin SDK 验证 Token。
Q Firestore 查询有索引限制吗?
A 复合查询需要创建复合索引。首次执行时 Firestore 会报错并给出创建索引的链接。
Q FCM 推送在中国大陆能用吗?
A 不能。中国大陆需要集成厂商推送(华为/小米/OPPO/VIVO),或使用极光推送等第三方服务。
Q Firestore 安全规则怎么调试?
A Firebase Console 的 Rules Playground 可以模拟读写请求测试规则。生产环境务必设置严格规则。

📖 小节


📝 作业

  1. 基础题(难度⭐):配置 Firebase 项目,实现 Email/Password 注册和登录,监听 authStateChanges 显示用户状态。
  2. 进阶题(难度⭐⭐):实现 Firestore 商品 CRUD + 实时监听,商品库存变化时 UI 自动更新。
  3. 挑战题(难度⭐⭐⭐):实现完整 Firebase 集成:Google 登录 + Firestore 实时商品 + Storage 图片上传(带进度)+ Analytics 事件追踪 + FCM 推送通知。

← 上一课 | 下一课 →

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏