Flutter: Firebase Integration

Firebase is Flutter's super assistant — Auth, database, storage, analytics, push notifications, all-in-one out of the box.

📋 Prerequisites: You should already be familiar with

1. What You'll Learn


2. A Real Story of a Self-Built Backend Collapse

(1) The Pain Point: High Ops Cost of Self-Built Backend

Bob's ShopApp self-built backend uses Node.js + PostgreSQL + S3, with a 3-person ops team and a monthly cost of 20 thousand USD. One database migration caused 4 hours of downtime, losing 50 thousand USD in orders. Real-time product inventory sync required WebSocket, which was complex and unstable in the self-built setup. Push notifications used a third-party service with frequent delays.

(2) The Firebase Suite Solution

Firebase provides Auth + Firestore + Storage + Analytics + FCM as a one-stop backend — no server ops needed, real-time data syncs automatically.

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

// ⚙️ Install dependencies: flutter pub add cloud_firestore

// Custom class definition source:
// - Product: see Lesson 11 json_serializable model (add fromFirestore factory constructor)

// 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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

(3) The Payoff: Zero Ops + Real-Time Sync + Halved Costs

After Bob migrated to Firebase, the backend ops team shrank by 2 people, monthly costs dropped from 20 thousand USD to 8 thousand USD, and real-time data latency went from seconds to milliseconds.


3. Firebase Architecture Overview

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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

(1) Firebase Service Matrix

Service Usage Pricing
Authentication User authentication Generous free tier
Cloud Firestore NoSQL real-time database Free tier: 50K reads/day
Cloud Storage File storage Free tier: 5GB
Analytics User behavior analytics Free
Cloud Messaging Push notifications Free
Crashlytics Crash reporting Free

4. Firebase Project Configuration

▶ Example

TEXT
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

: FlutterFire initialization

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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.
DART
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

// ⚙️ Install dependencies: flutter pub add firebase_core
// ⚙️ Project configuration: 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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

5. Authentication

(1) Sign-In Method Comparison

Method Complexity User Experience Use Case
Email/Password Low Medium General purpose
Google Sign-In Medium High Android preferred
Apple Sign-In Medium High iOS required
Anonymous Login Low High (frictionless) Try before registering
Phone Verification High Medium Identity verification

▶ Example

TEXT
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

: AuthService wrapper

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

// ⚙️ Install dependencies: 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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

▶ Example

TEXT
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

: 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';

// ⚙️ Install dependencies: flutter pub add firebase_auth flutter_riverpod riverpod_annotation
// ⚙️ Dev dependencies: flutter pub add --dev riverpod_generator build_runner

// Custom class definition source:
// - AuthService: see Section 5 AuthService wrapper in this lesson

@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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

6. Cloud Firestore

(1) Data Modeling

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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

▶ Example

TEXT
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

: Firestore CRUD

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

// ⚙️ Install dependencies: flutter pub add cloud_firestore

// Custom class definition source:
// - Product: see Lesson 11 json_serializable model (add fromFirestore factory constructor)

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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

▶ Example

TEXT
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

: Firestore security rules

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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

7. Cloud Storage

▶ Example

TEXT
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

: Product image upload and download

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

// ⚙️ Install dependencies: 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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

8. Analytics + Cloud Messaging

▶ Example

TEXT
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

: Analytics event tracking

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

// ⚙️ Install dependencies: flutter pub add firebase_analytics

// Custom class definition source:
// - Product: see Lesson 11 json_serializable model
// - Order: see Lesson 14 Order model

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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

▶ Example

TEXT
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

: FCM push notifications

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

// ⚙️ Install dependencies: 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
> Output: Run on a local Flutter SDK (Flutter 3.x / Dart 3.x). The Piston server does not have Flutter installed; use `flutter run` on your local machine for comparison. Actual UI/state may vary slightly by platform.

❓ FAQ

Q Is the Firebase free tier enough?
A Firestore offers 50K reads/20K writes/day for free — sufficient for small-scale apps. Million-level DAU requires a paid plan.
Q Firestore or Realtime Database?
A Use Firestore for new projects (more powerful queries, better data model). Realtime Database is only for scenarios requiring extremely low-latency real-time.
Q How to integrate Firebase Auth tokens with a backend API?
A Get a JWT with await user.getIdToken() and send it to the backend for verification. The backend uses Firebase Admin SDK to verify the token.
Q Do Firestore queries have index limits?
A Compound queries require composite indexes. The first execution will fail with an error containing a link to create the index.
Q Does FCM push work in mainland China?
A No. Mainland China requires integrating vendor-specific push (Huawei/Xiaomi/OPPO/VIVO) or third-party services like JPush.
Q How to debug Firestore security rules?
A Firebase Console's Rules Playground can simulate read/write requests to test rules. Always set strict rules in production.

📖 Summary


📝 Exercises

  1. Basic (Difficulty ⭐): Configure a Firebase project, implement Email/Password registration and login, and monitor authStateChanges to display user status.
  2. Intermediate (Difficulty ⭐⭐): Implement Firestore product CRUD + real-time listening, with the UI auto-updating when product stock changes.
  3. Challenge (Difficulty ⭐⭐⭐): Implement full Firebase integration: Google Sign-In + Firestore real-time products + Storage image upload (with progress) + Analytics event tracking + FCM push notifications.

← Previous Lesson | Next Lesson →

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

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

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