Flutter āđāļĨāļ° Firebase āđƒāļ™āļ›āļĩ 2026: āļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™, Firestore āđāļĨāļ°āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ

āđ€āļˆāļēāļ°āļĨāļķāļ Flutter Firebase: āļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āļ”āđ‰āļ§āļĒ firebase_auth, CRUD āļ‚āļ­āļ‡ Firestore āđāļĨāļ°āļŠāļ•āļĢāļĩāļĄāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ, āļāļŽāļ„āļ§āļēāļĄāļ›āļĨāļ­āļ”āļ āļąāļĒ āđāļĨāļ°āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒāļ—āļĩāđˆāļžāļšāļšāđˆāļ­āļĒāļžāļĢāđ‰āļ­āļĄāļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡āđ‚āļ„āđ‰āļ”

āļāļēāļĢāļœāļŠāļēāļ™āļĢāļ§āļĄ Flutter āđāļĨāļ° Firebase āđāļŠāļ”āļ‡āļŠāļ–āļēāļ›āļąāļ•āļĒāļāļĢāļĢāļĄāļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āđāļĨāļ°āļāļēāļ™āļ‚āđ‰āļ­āļĄāļđāļĨ Firestore

āļāļēāļĢāļœāļŠāļēāļ™āļĢāļ§āļĄ Flutter āļāļąāļš Firebase āļĒāļąāļ‡āļ„āļ‡āđ€āļ›āđ‡āļ™āļ•āļąāļ§āđ€āļĨāļ·āļ­āļāđāļšāđ‡āļāđ€āļ­āļ™āļ”āđŒāļ—āļĩāđˆāđ„āļ”āđ‰āļĢāļąāļšāļ„āļ§āļēāļĄāļ™āļīāļĒāļĄāļĄāļēāļāļ—āļĩāđˆāļŠāļļāļ”āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™ Flutter āđƒāļ™āļ›āļĩ 2026 āđ‚āļ”āļĒāļ‚āļąāļšāđ€āļ„āļĨāļ·āđˆāļ­āļ™āļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™ āļāļēāļ™āļ‚āđ‰āļ­āļĄāļđāļĨāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ āđāļĨāļ° cloud functions āđƒāļ™āđāļ­āļ›āļ™āļąāļšāļĨāđ‰āļēāļ™ āļ”āđ‰āļ§āļĒ FlutterFire SDK v4.15 āđ€āļ„āļĢāļ·āđˆāļ­āļ‡āļĄāļ·āļ­āļ•āđˆāļēāļ‡ āđ† āđ„āļ”āđ‰āļžāļąāļ’āļ™āļēāļ‚āļķāđ‰āļ™āļ­āļĒāđˆāļēāļ‡āļĄāļēāļ āļ•āļąāđ‰āļ‡āđāļ•āđˆāļāļēāļĢāļ•āļąāđ‰āļ‡āļ„āđˆāļēāļ—āļĩāđˆāļāļĢāļ°āļŠāļąāļšāļœāđˆāļēāļ™ flutterfire configure āđ„āļ›āļˆāļ™āļ–āļķāļ‡āļāļēāļĢāļĢāļ­āļ‡āļĢāļąāļšāļĢāļ°āļ”āļąāļšāļŠāļąāđ‰āļ™āļ™āļģāļŠāļģāļŦāļĢāļąāļš Firestore Pipelines āđāļĨāļ° Firebase Admin Dart SDK

FlutterFire SDK v4.15 (2026)

FlutterFire āļĢāļļāđˆāļ™āļĨāđˆāļēāļŠāļļāļ”āļĄāļēāļžāļĢāđ‰āļ­āļĄāļāļąāļš firebase_auth v6.1.2 āđāļĨāļ° cloud_firestore v6.4.1 āļĢāļ­āļ‡āļĢāļąāļš Firestore Pipelines āļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āđāļšāļš TOTP āļšāļ™ macOS āđāļĨāļ° API validatePassword āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļšāļąāļ‡āļ„āļąāļšāđƒāļŠāđ‰āļ™āđ‚āļĒāļšāļēāļĒāļĢāļŦāļąāļŠāļœāđˆāļēāļ™

āļāļēāļĢāļ•āļąāđ‰āļ‡āļ„āđˆāļē Firebase āđƒāļ™āđ‚āļ›āļĢāđ€āļˆāļāļ•āđŒ Flutter

āļāđˆāļ­āļ™āđ€āļ‚āļĩāļĒāļ™āđ‚āļ„āđ‰āļ” Firebase āđƒāļ” āđ† āđ‚āļ›āļĢāđ€āļˆāļāļ•āđŒāļˆāļģāđ€āļ›āđ‡āļ™āļ•āđ‰āļ­āļ‡āđ„āļ”āđ‰āļĢāļąāļšāļāļēāļĢāļāļģāļŦāļ™āļ”āļ„āđˆāļēāđ€āļĢāļīāđˆāļĄāļ•āđ‰āļ™āļ­āļĒāđˆāļēāļ‡āļ–āļđāļāļ•āđ‰āļ­āļ‡ FlutterFire CLI āļˆāļ°āļ—āļģāļāļēāļĢāļĨāļ‡āļ—āļ°āđ€āļšāļĩāļĒāļ™āđāļžāļĨāļ•āļŸāļ­āļĢāđŒāļĄāđ‚āļ”āļĒāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļīāđāļĨāļ°āļŠāļĢāđ‰āļēāļ‡āđ„āļŸāļĨāđŒāļāļēāļĢāļāļģāļŦāļ™āļ”āļ„āđˆāļēāļŠāļģāļŦāļĢāļąāļš Android, iOS, āđ€āļ§āđ‡āļš āđāļĨāļ° macOS

main.dartdart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'firebase_options.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Initialize Firebase with platform-specific config
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const MyApp());
}

āđ„āļŸāļĨāđŒ firebase_options.dart āļ–āļđāļāļŠāļĢāđ‰āļēāļ‡āļ‚āļķāđ‰āļ™āđ‚āļ”āļĒāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļīāđ€āļĄāļ·āđˆāļ­āļĢāļąāļ™ flutterfire configure āđ„āļŸāļĨāđŒāļ™āļĩāđ‰āļĄāļĩāļ„āļĩāļĒāđŒ API, āļĢāļŦāļąāļŠāđ‚āļ›āļĢāđ€āļˆāļāļ•āđŒ āđāļĨāļ°āļ•āļąāļ§āļĢāļ°āļšāļļāđ€āļ‰āļžāļēāļ°āđāļžāļĨāļ•āļŸāļ­āļĢāđŒāļĄ āđ‚āļ”āļĒāđ„āļĄāđˆāļ•āđ‰āļ­āļ‡āļ„āļąāļ”āļĨāļ­āļāļ”āđ‰āļ§āļĒāļ•āļ™āđ€āļ­āļ‡āļˆāļēāļ Firebase console

Firebase Authentication: āļ­āļĩāđ€āļĄāļĨ, Google āđāļĨāļ°āļŦāļĨāļēāļĒāļ›āļąāļˆāļˆāļąāļĒ

Firebase Authentication āļˆāļąāļ”āļāļēāļĢāļ•āļąāļ§āļ•āļ™āļ‚āļ­āļ‡āļœāļđāđ‰āđƒāļŠāđ‰āļ”āđ‰āļ§āļĒāđ‚āļ„āđ‰āļ”āļŠāļģāđ€āļĢāđ‡āļˆāļĢāļđāļ›āļ—āļĩāđˆāļ™āđ‰āļ­āļĒāļ—āļĩāđˆāļŠāļļāļ” āđāļžāđ‡āļāđ€āļāļˆ firebase_auth āļĢāļ­āļ‡āļĢāļąāļšāļ­āļĩāđ€āļĄāļĨ/āļĢāļŦāļąāļŠāļœāđˆāļēāļ™, āļœāļđāđ‰āđƒāļŦāđ‰āļšāļĢāļīāļāļēāļĢ OAuth (Google, Apple, GitHub), āļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļœāđˆāļēāļ™ SMS āļ—āļēāļ‡āđ‚āļ—āļĢāļĻāļąāļžāļ—āđŒ āđāļĨāļ°āļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āđāļšāļšāļŦāļĨāļēāļĒāļ›āļąāļˆāļˆāļąāļĒ

āļāļēāļĢāļĨāļ‡āļ—āļ°āđ€āļšāļĩāļĒāļ™āļ”āđ‰āļ§āļĒāļ­āļĩāđ€āļĄāļĨāđāļĨāļ°āļĢāļŦāļąāļŠāļœāđˆāļēāļ™

āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆāļžāļšāļšāđˆāļ­āļĒāļ—āļĩāđˆāļŠāļļāļ”āđ€āļĢāļīāđˆāļĄāļ•āđ‰āļ™āļ”āđ‰āļ§āļĒāļ­āļĩāđ€āļĄāļĨ/āļĢāļŦāļąāļŠāļœāđˆāļēāļ™ āđ€āļĄāļ˜āļ­āļ” createUserWithEmailAndPassword āļˆāļ°āļ„āļ·āļ™āļ„āđˆāļē UserCredential āļ—āļĩāđˆāļĄāļĩāļ­āđ‡āļ­āļšāđ€āļˆāļāļ•āđŒ User āļ—āļĩāđˆāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āđāļĨāđ‰āļ§

auth_service.dartdart
import 'package:firebase_auth/firebase_auth.dart';

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  // Register with email and password
  Future<User?> register(String email, String password) async {
    try {
      final credential = await _auth.createUserWithEmailAndPassword(
        email: email,
        password: password,
      );
      return credential.user;
    } on FirebaseAuthException catch (e) {
      // Handle specific error codes
      switch (e.code) {
        case 'email-already-in-use':
          throw Exception('This email is already registered');
        case 'weak-password':
          throw Exception('Password must be at least 6 characters');
        default:
          throw Exception('Registration failed: ${e.message}');
      }
    }
  }

  // Sign in with existing credentials
  Future<User?> signIn(String email, String password) async {
    final credential = await _auth.signInWithEmailAndPassword(
      email: email,
      password: password,
    );
    return credential.user;
  }

  // Reactive auth state stream
  Stream<User?> get authStateChanges => _auth.authStateChanges();
}

āļŠāļ•āļĢāļĩāļĄ authStateChanges() āđ€āļ›āđ‡āļ™āļ§āļīāļ˜āļĩāļ—āļĩāđˆāđāļ™āļ°āļ™āļģāđƒāļ™āļāļēāļĢāļ•āļīāļ”āļ•āļēāļĄāļŠāļ–āļēāļ™āļ°āļāļēāļĢāđ€āļ‚āđ‰āļēāļŠāļđāđˆāļĢāļ°āļšāļšāļ—āļąāđˆāļ§āļ—āļąāđ‰āļ‡āđāļ­āļ› āđ‚āļ”āļĒāļˆāļ°āļŠāđˆāļ‡āļ„āđˆāļē User āļ›āļąāļˆāļˆāļļāļšāļąāļ™āđ€āļĄāļ·āđˆāļ­āļĄāļĩāļāļēāļĢāļŠāļĄāļąāļ„āļĢāļĢāļąāļšāļ‚āđ‰āļ­āļĄāļđāļĨ āđāļĨāļ°āļ—āļģāļ‡āļēāļ™āļ­āļĩāļāļ„āļĢāļąāđ‰āļ‡āđƒāļ™āļ—āļļāļāđ€āļŦāļ•āļļāļāļēāļĢāļ“āđŒāļāļēāļĢāđ€āļ‚āđ‰āļēāļŠāļđāđˆāļĢāļ°āļšāļšāļŦāļĢāļ·āļ­āļ­āļ­āļāļˆāļēāļāļĢāļ°āļšāļš

āļāļēāļĢāļœāļŠāļēāļ™āļĢāļ§āļĄ Google Sign-In

āļœāļđāđ‰āđƒāļŦāđ‰āļšāļĢāļīāļāļēāļĢ OAuth āļ•āđ‰āļ­āļ‡āđƒāļŠāđ‰āđāļžāđ‡āļāđ€āļāļˆāđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ Google Sign-In āļˆāļ°āđ€āļĢāļĩāļĒāļāļ•āļąāļ§āđ€āļĨāļ·āļ­āļāļšāļąāļāļŠāļĩāđāļšāļšāđ€āļ™āļ—āļĩāļŸ āļˆāļēāļāļ™āļąāđ‰āļ™āđāļĨāļāđ€āļ›āļĨāļĩāđˆāļĒāļ™āđ‚āļ—āđ€āļ„āđ‡āļ™āļāļąāļš Firebase

google_auth.dartdart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

Future<UserCredential> signInWithGoogle() async {
  // Trigger the native Google Sign-In flow
  final googleUser = await GoogleSignIn().signIn();
  if (googleUser == null) throw Exception('Sign-in cancelled');

  // Obtain auth details from the Google account
  final googleAuth = await googleUser.authentication;

  // Create a Firebase credential from the Google tokens
  final credential = GoogleAuthProvider.credential(
    accessToken: googleAuth.accessToken,
    idToken: googleAuth.idToken,
  );

  // Sign in to Firebase with the Google credential
  return FirebaseAuth.instance.signInWithCredential(credential);
}

āļĢāļđāļ›āđāļšāļšāļ™āļĩāđ‰āđƒāļŠāđ‰āđ„āļ”āđ‰āļāļąāļšāļœāļđāđ‰āđƒāļŦāđ‰āļšāļĢāļīāļāļēāļĢ OAuth āļ—āļąāđ‰āļ‡āļŦāļĄāļ”: āļĢāļąāļšāđ‚āļ—āđ€āļ„āđ‡āļ™āļ‚āļ­āļ‡āļœāļđāđ‰āđƒāļŦāđ‰āļšāļĢāļīāļāļēāļĢ āļŦāđˆāļ­āļŦāļļāđ‰āļĄāđ„āļ§āđ‰āđƒāļ™ credential āļ‚āļ­āļ‡ Firebase āđāļĨāđ‰āļ§āđ€āļĢāļĩāļĒāļ signInWithCredential

āļāļēāļĢāļ•āļĢāļ§āļˆāļŠāļ­āļšāļ™āđ‚āļĒāļšāļēāļĒāļĢāļŦāļąāļŠāļœāđˆāļēāļ™

Firebase Auth v6.1+ āļĄāļĩ API validatePassword āļ‹āļķāđˆāļ‡āļŠāđˆāļ§āļĒāđƒāļŦāđ‰āļšāļąāļ‡āļ„āļąāļšāđƒāļŠāđ‰āļ™āđ‚āļĒāļšāļēāļĒāļĢāļŦāļąāļŠāļœāđˆāļēāļ™āļāļąāđˆāļ‡āđ€āļ‹āļīāļĢāđŒāļŸāđ€āļ§āļ­āļĢāđŒāđ„āļ”āđ‰ āļ™āđ‚āļĒāļšāļēāļĒāļŠāļēāļĄāļēāļĢāļ–āļāļģāļŦāļ™āļ”āļ„āļ§āļēāļĄāļĒāļēāļ§āļ‚āļąāđ‰āļ™āļ•āđˆāļģ āļ•āļąāļ§āļžāļīāļĄāļžāđŒāđƒāļŦāļāđˆ āļ•āļąāļ§āļžāļīāļĄāļžāđŒāđ€āļĨāđ‡āļ āļ•āļąāļ§āđ€āļĨāļ‚ āđāļĨāļ°āļ­āļąāļāļ‚āļĢāļ°āļžāļīāđ€āļĻāļĐ āļ‹āļķāđˆāļ‡āļ—āļąāđ‰āļ‡āļŦāļĄāļ”āļŠāļēāļĄāļēāļĢāļ–āļāļģāļŦāļ™āļ”āļ„āđˆāļēāđ„āļ”āđ‰āļˆāļēāļ Firebase console

āļāļēāļĢāļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢ CRUD āļ‚āļ­āļ‡ Firestore āđāļĨāļ°āļāļēāļĢāļŠāļĢāđ‰āļēāļ‡āđāļšāļšāļˆāļģāļĨāļ­āļ‡āļ‚āđ‰āļ­āļĄāļđāļĨ

Cloud Firestore āļˆāļąāļ”āļĢāļ°āđ€āļšāļĩāļĒāļšāļ‚āđ‰āļ­āļĄāļđāļĨāđ€āļ›āđ‡āļ™ collection āđāļĨāļ° document āļ•āđˆāļēāļ‡āļˆāļēāļāļāļēāļ™āļ‚āđ‰āļ­āļĄāļđāļĨ SQL āļ•āļĢāļ‡āļ—āļĩāđˆ Firestore āđ„āļĄāđˆāļĄāļĩ schema āđ€āļ­āļāļŠāļēāļĢāđāļ•āđˆāļĨāļ°āļ‰āļšāļąāļšāļŠāļēāļĄāļēāļĢāļ–āļĄāļĩāļŸāļīāļĨāļ”āđŒāļ—āļĩāđˆāđāļ•āļāļ•āđˆāļēāļ‡āļāļąāļ™āđ„āļ”āđ‰ āļ„āļ§āļēāļĄāļĒāļ·āļ”āļŦāļĒāļļāđˆāļ™āļ™āļĩāđ‰āđ€āļŦāļĄāļēāļ°āļāļąāļšāđāļ­āļ› Flutter āđāļ•āđˆāļ•āđ‰āļ­āļ‡āļāļēāļĢāļāļēāļĢāļŠāļĢāđ‰āļēāļ‡āđāļšāļšāļˆāļģāļĨāļ­āļ‡āļ‚āđ‰āļ­āļĄāļđāļĨāļ­āļĒāđˆāļēāļ‡āļĄāļĩāļ§āļīāļ™āļąāļĒāđ€āļžāļ·āđˆāļ­āļŦāļĨāļĩāļāđ€āļĨāļĩāđˆāļĒāļ‡āļ›āļąāļāļŦāļēāļ”āđ‰āļēāļ™āļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļž

āļāļēāļĢāđ€āļ‚āļĩāļĒāļ™āđāļĨāļ°āļāļēāļĢāļ­āđˆāļēāļ™ Document

āļāļēāļĢāļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢāļ‚āļ­āļ‡ Firestore āļ—āļģāđ„āļ”āđ‰āļ­āļĒāđˆāļēāļ‡āļ•āļĢāļ‡āđ„āļ›āļ•āļĢāļ‡āļĄāļēāļ”āđ‰āļ§āļĒāđāļžāđ‡āļāđ€āļāļˆ cloud_firestore āļ—āļļāļāļāļēāļĢāļ­āđˆāļēāļ™āđāļĨāļ°āļāļēāļĢāđ€āļ‚āļĩāļĒāļ™āļˆāļ°āļĄāļļāđˆāļ‡āđ€āļ›āđ‰āļēāđ„āļ›āļ—āļĩāđˆāđ€āļŠāđ‰āļ™āļ—āļēāļ‡āļ‚āļ­āļ‡ document āļ—āļĩāđˆāđ€āļ‰āļžāļēāļ°āđ€āļˆāļēāļ°āļˆāļ‡

firestore_service.dartdart
import 'package:cloud_firestore/cloud_firestore.dart';

class TaskService {
  final _db = FirebaseFirestore.instance;
  final String _collection = 'tasks';

  // Create a new document with auto-generated ID
  Future<String> createTask(String userId, String title) async {
    final doc = await _db.collection(_collection).add({
      'userId': userId,
      'title': title,
      'completed': false,
      'createdAt': FieldValue.serverTimestamp(),
    });
    return doc.id;
  }

  // Read a single document by ID
  Future<Map<String, dynamic>?> getTask(String taskId) async {
    final snapshot = await _db.collection(_collection).doc(taskId).get();
    return snapshot.data();
  }

  // Update specific fields without overwriting the entire document
  Future<void> toggleComplete(String taskId, bool completed) async {
    await _db.collection(_collection).doc(taskId).update({
      'completed': completed,
      'updatedAt': FieldValue.serverTimestamp(),
    });
  }

  // Delete a document
  Future<void> deleteTask(String taskId) async {
    await _db.collection(_collection).doc(taskId).delete();
  }
}

FieldValue.serverTimestamp() āļĢāļąāļšāļ›āļĢāļ°āļāļąāļ™ timestamp āļ—āļĩāđˆāļŠāļ­āļ”āļ„āļĨāđ‰āļ­āļ‡āļāļąāļ™āđƒāļ™āļ—āļļāļāļ­āļļāļ›āļāļĢāļ“āđŒ āđ‚āļ”āļĒāđƒāļŠāđ‰āļ™āļēāļŽāļīāļāļēāļ‚āļ­āļ‡āđ€āļ‹āļīāļĢāđŒāļŸāđ€āļ§āļ­āļĢāđŒ Firestore āđāļ—āļ™āļ™āļēāļŽāļīāļāļēāļ‚āļ­āļ‡āđ„āļ„āļĨāđ€āļ­āļ™āļ•āđŒ

āļŠāļ•āļĢāļĩāļĄāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒāļ”āđ‰āļ§āļĒ snapshots()

Firestore āđ‚āļ”āļ”āđ€āļ”āđˆāļ™āļ”āđ‰āļ§āļĒāļāļēāļĢāļ‹āļīāļ‡āđ‚āļ„āļĢāđ„āļ™āļ‹āđŒāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ āđ€āļĄāļ˜āļ­āļ” snapshots() āļ„āļ·āļ™āļ„āđˆāļē Stream āļ—āļĩāđˆāļŠāđˆāļ‡āļ‚āđ‰āļ­āļĄāļđāļĨāđƒāļŦāļĄāđˆāļ—āļļāļāļ„āļĢāļąāđ‰āļ‡āļ—āļĩāđˆ document āļ—āļĩāđˆāđ€āļāļĩāđˆāļĒāļ§āļ‚āđ‰āļ­āļ‡āļĄāļĩāļāļēāļĢāđ€āļ›āļĨāļĩāđˆāļĒāļ™āđāļ›āļĨāļ‡ āđ‚āļ”āļĒāđ„āļĄāđˆāļ•āđ‰āļ­āļ‡ polling

real_time_tasks.dartdart
import 'package:cloud_firestore/cloud_firestore.dart';

class TaskStream {
  final _db = FirebaseFirestore.instance;

  // Stream all tasks for a specific user, ordered by creation date
  Stream<List<Map<String, dynamic>>> userTasks(String userId) {
    return _db
        .collection('tasks')
        .where('userId', isEqualTo: userId)
        .orderBy('createdAt', descending: true)
        .snapshots()
        .map((snapshot) => snapshot.docs.map((doc) {
              final data = doc.data();
              data['id'] = doc.id; // Include document ID
              return data;
            }).toList());
  }
}

āļ āļēāļĒāđƒāļ™ widget āļ‚āļ­āļ‡ Flutter āļŠāļ•āļĢāļĩāļĄāļ™āļĩāđ‰āļœāļŠāļēāļ™āļĢāļ§āļĄāđ‚āļ”āļĒāļ•āļĢāļ‡āļāļąāļš StreamBuilder āđ€āļžāļ·āđˆāļ­āļŠāļĢāđ‰āļēāļ‡ UI āđƒāļŦāļĄāđˆāđƒāļ™āļ—āļļāļāļāļēāļĢāđ€āļ›āļĨāļĩāđˆāļĒāļ™āđāļ›āļĨāļ‡āļ‚āļ­āļ‡āļāļēāļ™āļ‚āđ‰āļ­āļĄāļđāļĨ Firestore āļˆāļąāļ”āļāļēāļĢāļāļēāļĢāđ€āļŠāļ·āđˆāļ­āļĄāļ•āđˆāļ­ āļāļēāļĢāđāļ„āļŠ āđāļĨāļ°āļāļēāļĢāļ„āļ‡āļ­āļĒāļđāđˆāđāļšāļšāļ­āļ­āļŸāđ„āļĨāļ™āđŒāđ‚āļ”āļĒāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļī

āļžāļĢāđ‰āļ­āļĄāļ—āļĩāđˆāļˆāļ°āļžāļīāļŠāļīāļ•āļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Flutter āđāļĨāđ‰āļ§āļŦāļĢāļ·āļ­āļĒāļąāļ‡āļ„āļĢāļąāļš?

āļāļķāļāļāļ™āļ”āđ‰āļ§āļĒāļ•āļąāļ§āļˆāļģāļĨāļ­āļ‡āđāļšāļšāđ‚āļ•āđ‰āļ•āļ­āļš, flashcards āđāļĨāļ°āđāļšāļšāļ—āļ”āļŠāļ­āļšāđ€āļ—āļ„āļ™āļīāļ„āļ„āļĢāļąāļš

āļāļŽāļ„āļ§āļēāļĄāļ›āļĨāļ­āļ”āļ āļąāļĒāļ‚āļ­āļ‡ Firestore āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ› Flutter

āļāļŽāļ„āļ§āļēāļĄāļ›āļĨāļ­āļ”āļ āļąāļĒāļ—āļģāļ‡āļēāļ™āļšāļ™āđ€āļ‹āļīāļĢāđŒāļŸāđ€āļ§āļ­āļĢāđŒ Firestore āđāļĨāļ°āļ„āļ§āļšāļ„āļļāļĄāļŠāļīāļ—āļ˜āļīāđŒāļāļēāļĢāļ­āđˆāļēāļ™/āđ€āļ‚āļĩāļĒāļ™āđƒāļ™āļĢāļ°āļ”āļąāļš document āļŦāļēāļāđ„āļĄāđˆāļĄāļĩāļāļŽāļ—āļĩāđˆāđ€āļŦāļĄāļēāļ°āļŠāļĄ āļœāļđāđ‰āđƒāļŠāđ‰āļ—āļĩāđˆāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āđāļĨāđ‰āļ§āļ—āļļāļāļ„āļ™āļŠāļēāļĄāļēāļĢāļ–āļ­āđˆāļēāļ™āļŦāļĢāļ·āļ­āđāļāđ‰āđ„āļ‚ document āđƒāļ”āļāđ‡āđ„āļ”āđ‰

firestore.rulesjavascript
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Users can only access their own profile
    match /users/{userId} {
      allow read, update: if request.auth != null
                          && request.auth.uid == userId;
      allow create: if request.auth != null;
      allow delete: if false; // Prevent self-deletion
    }

    // Tasks belong to the user who created them
    match /tasks/{taskId} {
      allow read, write: if request.auth != null
                         && resource.data.userId == request.auth.uid;
      allow create: if request.auth != null
                    && request.resource.data.userId == request.auth.uid;
    }
  }
}

āļ•āļąāļ§āđāļ›āļĢ request.auth.uid āļĄāļĩ ID āļ‚āļ­āļ‡āļœāļđāđ‰āđƒāļŠāđ‰āļ—āļĩāđˆāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āđāļĨāđ‰āļ§āļˆāļēāļ Firebase Auth āļāļŽāļ—āļĩāđˆāļ­āđ‰āļēāļ‡āļ­āļīāļ‡ resource.data āļˆāļ°āļ•āļĢāļ§āļˆāļŠāļ­āļšāļŸāļīāļĨāļ”āđŒāļ‚āļ­āļ‡ document āļ—āļĩāđˆāļĄāļĩāļ­āļĒāļđāđˆ āđƒāļ™āļ‚āļ“āļ°āļ—āļĩāđˆ request.resource.data āļˆāļ°āļ•āļĢāļ§āļˆāļŠāļ­āļšāļ‚āđ‰āļ­āļĄāļđāļĨāļāļēāļĢāđ€āļ‚āļĩāļĒāļ™āļ—āļĩāđˆāļāļģāļĨāļąāļ‡āđ€āļ‚āđ‰āļēāļĄāļē

āļāļŽāļ„āļ§āļēāļĄāļ›āļĨāļ­āļ”āļ āļąāļĒāđ„āļĄāđˆāđƒāļŠāđˆāļ—āļēāļ‡āđ€āļĨāļ·āļ­āļ

Firestore āļˆāļ°āļ›āļāļīāđ€āļŠāļ˜āļāļēāļĢāđ€āļ‚āđ‰āļēāļ–āļķāļ‡āļ—āļąāđ‰āļ‡āļŦāļĄāļ”āđ€āļ›āđ‡āļ™āļ„āđˆāļēāđ€āļĢāļīāđˆāļĄāļ•āđ‰āļ™āđƒāļ™āđ‚āļŦāļĄāļ” production āļ—āļļāļ collection āļ•āđ‰āļ­āļ‡āļĄāļĩāļāļŽāļ—āļĩāđˆāļŠāļąāļ”āđ€āļˆāļ™ āļ‚āđ‰āļ­āļœāļīāļ”āļžāļĨāļēāļ”āļ—āļĩāđˆāļžāļšāļšāđˆāļ­āļĒāđƒāļ™āđ‚āļ›āļĢāđ€āļˆāļāļ•āđŒ Flutter: āļāļēāļĢāļžāļąāļ’āļ™āļēāļ”āđ‰āļ§āļĒāļāļŽāđ‚āļŦāļĄāļ”āļ—āļ”āļŠāļ­āļš (allow read, write: if true) āđāļĨāđ‰āļ§āļĨāļ·āļĄāļĨāđ‡āļ­āļāļāđˆāļ­āļ™āļ™āļģāļ‚āļķāđ‰āļ™ production

āļāļēāļĢāļ„āļ‡āļ­āļĒāļđāđˆāđāļšāļšāļ­āļ­āļŸāđ„āļĨāļ™āđŒāđāļĨāļ°āļāļĨāļĒāļļāļ—āļ˜āđŒāļāļēāļĢāđāļ„āļŠ

Firestore āđ€āļ›āļīāļ”āđƒāļŠāđ‰āļ‡āļēāļ™āļāļēāļĢāļ„āļ‡āļ­āļĒāļđāđˆāđāļšāļšāļ­āļ­āļŸāđ„āļĨāļ™āđŒāđ€āļ›āđ‡āļ™āļ„āđˆāļēāđ€āļĢāļīāđˆāļĄāļ•āđ‰āļ™āļšāļ™āđāļžāļĨāļ•āļŸāļ­āļĢāđŒāļĄāļĄāļ·āļ­āļ–āļ·āļ­ āđ€āļĄāļ·āđˆāļ­āļ­āļļāļ›āļāļĢāļ“āđŒāļŠāļđāļāđ€āļŠāļĩāļĒāļāļēāļĢāđ€āļŠāļ·āđˆāļ­āļĄāļ•āđˆāļ­ āļāļēāļĢāļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢāļ­āđˆāļēāļ™āļˆāļ°āļ„āļ·āļ™āļ„āđˆāļēāļ‚āđ‰āļ­āļĄāļđāļĨāļ—āļĩāđˆāđāļ„āļŠāđ„āļ§āđ‰ āđāļĨāļ°āļāļēāļĢāļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢāđ€āļ‚āļĩāļĒāļ™āļˆāļ°āđ€āļ‚āđ‰āļēāļ„āļīāļ§āļ āļēāļĒāđƒāļ™āđ€āļ„āļĢāļ·āđˆāļ­āļ‡āļˆāļ™āļāļ§āđˆāļēāļāļēāļĢāđ€āļŠāļ·āđˆāļ­āļĄāļ•āđˆāļ­āļˆāļ°āļāļĨāļąāļšāļĄāļē

āļžāļĪāļ•āļīāļāļĢāļĢāļĄāļ™āļĩāđ‰āđ‚āļ›āļĢāđˆāļ‡āđƒāļŠāļ•āđˆāļ­āđ‚āļ„āđ‰āļ” Flutter āļāļēāļĢāđ€āļĢāļĩāļĒāļ get() āđāļĨāļ° snapshots() āđ€āļ”āļīāļĄāļĒāļąāļ‡āļ„āļ‡āļ—āļģāļ‡āļēāļ™āđ„āļ”āđ‰āļ‚āļ“āļ°āļ­āļ­āļŸāđ„āļĨāļ™āđŒ āļ­āļĒāđˆāļēāļ‡āđ„āļĢāļāđ‡āļ•āļēāļĄ āļĄāļĩāļŠāļ­āļ‡āļŠāļīāđˆāļ‡āļ—āļĩāđˆāļ•āđ‰āļ­āļ‡āļžāļīāļˆāļēāļĢāļ“āļēāļŠāļģāļŦāļĢāļąāļšāđāļ­āļ› production:

  • āļ‚āļ™āļēāļ”āđāļ„āļŠ: Firestore āđāļ„āļŠ document āļ—āļąāđ‰āļ‡āļŦāļĄāļ”āļ—āļĩāđˆāđ„āļ„āļĨāđ€āļ­āļ™āļ•āđŒāđ„āļ”āđ‰āļ­āđˆāļēāļ™ āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ›āļ—āļĩāđˆāļĄāļĩāļ‚āđ‰āļ­āļĄāļđāļĨāļˆāļģāļ™āļ§āļ™āļĄāļēāļ āđƒāļŦāđ‰āļāļģāļŦāļ™āļ”āļ„āđˆāļē Settings(cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED) āļŦāļĢāļ·āļ­āļāļģāļŦāļ™āļ”āļ‚āļĩāļ”āļˆāļģāļāļąāļ”āļ—āļĩāđˆāđ€āļ‰āļžāļēāļ°āđ€āļˆāļēāļ°āļˆāļ‡ āļĢāļļāđˆāļ™ v6.4.1 āđ„āļ”āđ‰āđāļāđ‰āđ„āļ‚āļšāļąāđŠāļāļ—āļĩāđˆāđāļ„āļŠāđāļšāļšāđ„āļĄāđˆāļˆāļģāļāļąāļ”āđ„āļĄāđˆāļ–āļđāļāļ™āļģāđ„āļ›āđƒāļŠāđ‰āļ­āļĒāđˆāļēāļ‡āļ–āļđāļāļ•āđ‰āļ­āļ‡āļšāļ™ iOS
  • āļ•āļąāļ§āļšāđˆāļ‡āļŠāļĩāđ‰āļāļēāļĢāđ€āļ‚āļĩāļĒāļ™āļ—āļĩāđˆāļĢāļ­āļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢ: āđƒāļŠāđ‰ SnapshotMetadata.hasPendingWrites āđ€āļžāļ·āđˆāļ­āđāļŠāļ”āļ‡āđƒāļŦāđ‰āļœāļđāđ‰āđƒāļŠāđ‰āļ—āļĢāļēāļšāļ§āđˆāļēāļāļēāļĢāđ€āļ›āļĨāļĩāđˆāļĒāļ™āđāļ›āļĨāļ‡āđƒāļ™āđ€āļ„āļĢāļ·āđˆāļ­āļ‡āļĒāļąāļ‡āđ„āļĄāđˆāđ„āļ”āđ‰āļ‹āļīāļ‡āļ„āđŒāđ„āļ›āļĒāļąāļ‡āđ€āļ‹āļīāļĢāđŒāļŸāđ€āļ§āļ­āļĢāđŒ
offline_aware_widget.dartdart
StreamBuilder<DocumentSnapshot>(
  stream: FirebaseFirestore.instance
      .collection('tasks')
      .doc(taskId)
      .snapshots(),
  builder: (context, snapshot) {
    if (!snapshot.hasData) return const CircularProgressIndicator();

    final data = snapshot.data!;
    final isPending = data.metadata.hasPendingWrites;

    return Row(
      children: [
        Text(data['title']),
        if (isPending) const Icon(Icons.cloud_upload, size: 16),
      ],
    );
  },
)

āļāļēāļĢāļˆāļąāļ”āđ‚āļ„āļĢāļ‡āļŠāļĢāđ‰āļēāļ‡āđāļ­āļ› Flutter Firebase āļŠāļģāļŦāļĢāļąāļš Production

āļŠāļ–āļēāļ›āļąāļ•āļĒāļāļĢāļĢāļĄāļ—āļĩāđˆāļ‚āļĒāļēāļĒāļ‚āļ™āļēāļ”āđ„āļ”āđ‰āļˆāļ°āđāļĒāļāļ•āļĢāļĢāļāļ°āļ‚āļ­āļ‡ Firebase āļ­āļ­āļāļˆāļēāļāđ‚āļ„āđ‰āļ” UI āļĢāļđāļ›āđāļšāļš repository āļĄāļ­āļšāļŠāļąāđ‰āļ™āļāļēāļĢāļ™āļēāļĄāļ˜āļĢāļĢāļĄāļ—āļĩāđˆāļŠāļąāļ”āđ€āļˆāļ™āļ‹āļķāđˆāļ‡āļŠāđˆāļ§āļĒāđƒāļŦāđ‰āļāļēāļĢāļ—āļ”āļŠāļ­āļšāđāļĨāļ°āļāļēāļĢāļĒāđ‰āļēāļĒāđāļšāđ‡āļāđ€āļ­āļ™āļ”āđŒāđƒāļ™āļ­āļ™āļēāļ„āļ•āļ‡āđˆāļēāļĒāļ‚āļķāđ‰āļ™

task_repository.dartdart
abstract class TaskRepository {
  Future<String> create(String userId, String title);
  Stream<List<Task>> watchAll(String userId);
  Future<void> update(String id, Map<String, dynamic> fields);
  Future<void> delete(String id);
}

// firebase_task_repository.dart
class FirebaseTaskRepository implements TaskRepository {
  final _db = FirebaseFirestore.instance;

  
  Future<String> create(String userId, String title) async {
    final doc = await _db.collection('tasks').add({
      'userId': userId,
      'title': title,
      'completed': false,
      'createdAt': FieldValue.serverTimestamp(),
    });
    return doc.id;
  }

  
  Stream<List<Task>> watchAll(String userId) {
    return _db
        .collection('tasks')
        .where('userId', isEqualTo: userId)
        .orderBy('createdAt', descending: true)
        .snapshots()
        .map((s) => s.docs.map(Task.fromFirestore).toList());
  }

  // ... update and delete implementations
}

āļ”āđ‰āļ§āļĒāļĢāļđāļ›āđāļšāļšāļ™āļĩāđ‰ āđ‚āļ‹āļĨāļđāļŠāļąāļ™āļāļēāļĢāļˆāļąāļ”āļāļēāļĢ state āļ­āļĒāđˆāļēāļ‡ Riverpod āļŦāļĢāļ·āļ­ BLoC āļˆāļ°āđƒāļŠāđ‰āļ­āļīāļ™āđ€āļ—āļ­āļĢāđŒāđ€āļŸāļ‹ repository āđ‚āļ”āļĒāđ„āļĄāđˆāļ•āđ‰āļ­āļ‡āļĢāļđāđ‰āđ€āļāļĩāđˆāļĒāļ§āļāļąāļš Firestore āļāļēāļĢāļ—āļ”āļŠāļ­āļšāļŦāļ™āđˆāļ§āļĒāļŠāļēāļĄāļēāļĢāļ–āđāļ—āļ™āļ—āļĩāđˆāļ”āđ‰āļ§āļĒ mock repository āļ—āļĩāđˆāļ„āļ·āļ™āļ„āđˆāļēāļ‚āđ‰āļ­āļĄāļđāļĨāļ—āļĩāđˆāļāļģāļŦāļ™āļ”āđ„āļ§āđ‰āļĨāđˆāļ§āļ‡āļŦāļ™āđ‰āļēāđ„āļ”āđ‰

āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Flutter Firebase āļ—āļĩāđˆāļžāļšāļšāđˆāļ­āļĒ

āļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļ“āđŒāļĄāļąāļāļ—āļ”āļŠāļ­āļšāļ—āļąāđ‰āļ‡āļ„āļ§āļēāļĄāđ€āļ‚āđ‰āļēāđƒāļˆāđ€āļŠāļīāļ‡āđāļ™āļ§āļ„āļīāļ”āđāļĨāļ°āļāļēāļĢāļ™āļģāļšāļĢāļīāļāļēāļĢ Firebase āđ„āļ›āđƒāļŠāđ‰āļˆāļĢāļīāļ‡ āļ„āļģāļ–āļēāļĄāļ•āđˆāļ­āđ„āļ›āļ™āļĩāđ‰āļ›āļĢāļēāļāļāđ€āļ›āđ‡āļ™āļ›āļĢāļ°āļˆāļģāđƒāļ™āļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļ“āđŒāļ™āļąāļāļžāļąāļ’āļ™āļē Flutter āđƒāļ™āļ›āļĩ 2026

authStateChanges() āđāļ•āļāļ•āđˆāļēāļ‡āļˆāļēāļ idTokenChanges() āđāļĨāļ° userChanges() āļ­āļĒāđˆāļēāļ‡āđ„āļĢ?

authStateChanges() āļ—āļģāļ‡āļēāļ™āđ€āļ‰āļžāļēāļ°āđƒāļ™āđ€āļŦāļ•āļļāļāļēāļĢāļ“āđŒāļāļēāļĢāđ€āļ‚āđ‰āļēāļŠāļđāđˆāļĢāļ°āļšāļšāđāļĨāļ°āļ­āļ­āļāļˆāļēāļāļĢāļ°āļšāļšāđ€āļ—āđˆāļēāļ™āļąāđ‰āļ™ idTokenChanges() āļˆāļ°āļ—āļģāļ‡āļēāļ™āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄāđ€āļĄāļ·āđˆāļ­ ID token āļ–āļđāļāļĢāļĩāđ€āļŸāļĢāļŠ (āļ—āļļāļ āđ† āļ›āļĢāļ°āļĄāļēāļ“ 60 āļ™āļēāļ—āļĩ) userChanges() āļˆāļąāļšāļ—āļļāļāļ­āļĒāđˆāļēāļ‡āļ‚āđ‰āļēāļ‡āļ•āđ‰āļ™āļĢāļ§āļĄāļ–āļķāļ‡āļāļēāļĢāļ­āļąāļ›āđ€āļ”āļ•āđ‚āļ›āļĢāđ„āļŸāļĨāđŒāļ­āļĒāđˆāļēāļ‡ updateDisplayName() āļŠāļģāļŦāļĢāļąāļš navigation guard āļŠāđˆāļ§āļ™āđƒāļŦāļāđˆ authStateChanges() āļāđ‡āđ€āļžāļĩāļĒāļ‡āļžāļ­āđāļĨāđ‰āļ§

āđ€āļāļīāļ”āļ­āļ°āđ„āļĢāļ‚āļķāđ‰āļ™āđ€āļĄāļ·āđˆāļ­āļĄāļĩāļāļēāļĢāđ€āļ‚āļĩāļĒāļ™ Firestore āļ‚āļ“āļ°āļ—āļĩāđˆāļ­āļļāļ›āļāļĢāļ“āđŒāļ­āļ­āļŸāđ„āļĨāļ™āđŒ?

āļāļēāļĢāđ€āļ‚āļĩāļĒāļ™āļˆāļ°āļ–āļđāļāđ€āļāđ‡āļšāđ„āļ§āđ‰āđƒāļ™āđāļ„āļŠāļ āļēāļĒāđƒāļ™āđ€āļ„āļĢāļ·āđˆāļ­āļ‡āđāļĨāļ°āļ„āļīāļ§āļāļēāļĢāđ€āļ‚āļĩāļĒāļ™āļ—āļĩāđˆāļĢāļ­āļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢ āļ•āļąāļ§āļĢāļąāļšāļŸāļąāļ‡ snapshots() āļˆāļ°āđ„āļ”āđ‰āļĢāļąāļšāļ‚āđ‰āļ­āļĄāļđāļĨāļ—āļĩāđˆāļ­āļąāļ›āđ€āļ”āļ•āļ—āļąāļ™āļ—āļĩāļžāļĢāđ‰āļ­āļĄ metadata.hasPendingWrites == true āđ€āļĄāļ·āđˆāļ­āļāļēāļĢāđ€āļŠāļ·āđˆāļ­āļĄāļ•āđˆāļ­āļāļĨāļąāļšāļĄāļē Firestore āļˆāļ°āļ‹āļīāļ‡āļ„āđŒāļāļēāļĢāđ€āļ‚āļĩāļĒāļ™āļ—āļĩāđˆāļĢāļ­āļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢāđ‚āļ”āļĒāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļīāļ”āđ‰āļ§āļĒāļāļēāļĢāđāļāđ‰āđ„āļ‚āļ‚āđ‰āļ­āļ‚āļąāļ”āđāļĒāđ‰āļ‡āđāļšāļš last-writer-wins āđƒāļ™āļĢāļ°āļ”āļąāļšāļŸāļīāļĨāļ”āđŒ

āļ„āļ§āļĢāļŠāļĢāđ‰āļēāļ‡āđāļšāļšāļˆāļģāļĨāļ­āļ‡āļ‚āđ‰āļ­āļĄāļđāļĨ Firestore āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ›āđāļŠāļ—āļ­āļĒāđˆāļēāļ‡āđ„āļĢ?

āđāļ™āļ§āļ—āļēāļ‡āļ—āļĩāđˆāļžāļšāļšāđˆāļ­āļĒ: collection chats āļ—āļĩāđˆāđāļ•āđˆāļĨāļ° document āļĄāļĩ metadata (āļœāļđāđ‰āđ€āļ‚āđ‰āļēāļĢāđˆāļ§āļĄ, timestamp āļ‚āļ­āļ‡āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāļĨāđˆāļēāļŠāļļāļ”) āđāļĨāļ° subcollection messages āļ āļēāļĒāđƒāļ•āđ‰āđāļ•āđˆāļĨāļ° document āļ‚āļ­āļ‡āđāļŠāļ— āđ‚āļ„āļĢāļ‡āļŠāļĢāđ‰āļēāļ‡āļ™āļĩāđ‰āļŠāđˆāļ§āļĒāđƒāļŦāđ‰āļŠāļēāļĄāļēāļĢāļ– query āļĢāļēāļĒāļāļēāļĢāđāļŠāļ—āļ‚āļ­āļ‡āļœāļđāđ‰āđƒāļŠāđ‰āđ„āļ”āđ‰āļ­āļĒāđˆāļēāļ‡āļĄāļĩāļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļž āļžāļĢāđ‰āļ­āļĄāļ—āļąāđ‰āļ‡āđāļšāđˆāļ‡āļŦāļ™āđ‰āļēāļ‚āđ‰āļ­āļ„āļ§āļēāļĄāļ āļēāļĒāđƒāļ™āđāļ•āđˆāļĨāļ°āļšāļ—āļŠāļ™āļ—āļ™āļē āļ„āļ§āļĢ denormalize āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāļĨāđˆāļēāļŠāļļāļ”āđ€āļ‚āđ‰āļēāđ„āļ›āđƒāļ™ document āđāļĄāđˆ āđ€āļžāļ·āđˆāļ­āļŦāļĨāļĩāļāđ€āļĨāļĩāđˆāļĒāļ‡āļāļēāļĢāļ­āđˆāļēāļ™ subcollection āļŠāļģāļŦāļĢāļąāļšāļĄāļļāļĄāļĄāļ­āļ‡āļĢāļēāļĒāļāļēāļĢ

āļ—āļģāđ„āļĄāļˆāļķāļ‡āļ„āļ§āļĢāđƒāļŠāđ‰ FieldValue.serverTimestamp() āļĄāļēāļāļāļ§āđˆāļē DateTime.now()?

DateTime.now() āđƒāļŠāđ‰āļ™āļēāļŽāļīāļāļēāļ‚āļ­āļ‡āļ­āļļāļ›āļāļĢāļ“āđŒ āļ‹āļķāđˆāļ‡āļ­āļēāļˆāđ„āļĄāđˆāđāļĄāđˆāļ™āļĒāļģāļŦāļĢāļ·āļ­āļ–āļđāļāļ”āļąāļ”āđāļ›āļĨāļ‡āđ„āļ”āđ‰ FieldValue.serverTimestamp() āđƒāļŠāđ‰āļ™āļēāļŽāļīāļāļēāļ‚āļ­āļ‡āđ€āļ‹āļīāļĢāđŒāļŸāđ€āļ§āļ­āļĢāđŒ Firestore āļ‹āļķāđˆāļ‡āļĢāļąāļšāļ›āļĢāļ°āļāļąāļ™āļĨāļģāļ”āļąāļšāļ—āļĩāđˆāļŠāļ­āļ”āļ„āļĨāđ‰āļ­āļ‡āļāļąāļ™āđƒāļ™āļ—āļļāļāđ„āļ„āļĨāđ€āļ­āļ™āļ•āđŒ āļŠāļīāđˆāļ‡āļ™āļĩāđ‰āļŠāļģāļ„āļąāļāļŠāļģāļŦāļĢāļąāļšāļŸāļĩāđ€āļˆāļ­āļĢāđŒāļ­āļĒāđˆāļēāļ‡āļāļēāļĢāđ€āļĢāļĩāļĒāļ‡āļĨāļģāļ”āļąāļšāļ‚āđ‰āļ­āļ„āļ§āļēāļĄ āļŸāļĩāļ”āļāļīāļˆāļāļĢāļĢāļĄ āđāļĨāļ°āļšāļąāļ™āļ—āļķāļāļāļēāļĢāļ•āļĢāļ§āļˆāļŠāļ­āļš

āļāļēāļĢ query āđāļšāļš composite āļˆāļąāļ”āļāļēāļĢāļ­āļĒāđˆāļēāļ‡āđ„āļĢāđƒāļ™ Firestore āđāļĨāļ°āļĄāļĩāļ‚āđ‰āļ­āļāļģāļŦāļ™āļ”āđ€āļĢāļ·āđˆāļ­āļ‡ index āļ­āļĒāđˆāļēāļ‡āđ„āļĢ?

Firestore āļ•āđ‰āļ­āļ‡āļāļēāļĢ composite index āļŠāļģāļŦāļĢāļąāļš query āļ—āļĩāđˆāļĢāļ§āļĄāļŦāļĨāļēāļĒāļŸāļīāļĨāļ”āđŒāļ”āđ‰āļ§āļĒāļ­āļ™āļļāļ›āļĢāļ°āđ‚āļĒāļ„ where āđāļĨāļ° orderBy index āđāļšāļšāļŸāļīāļĨāļ”āđŒāđ€āļ”āļĩāļĒāļ§āļˆāļ°āļ–āļđāļāļŠāļĢāđ‰āļēāļ‡āđ‚āļ”āļĒāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļī āđāļ•āđˆ composite index āļ•āđ‰āļ­āļ‡āļ–āļđāļāļāļģāļŦāļ™āļ”āļ”āđ‰āļ§āļĒāļ•āļ™āđ€āļ­āļ‡āđƒāļ™ firestore.indexes.json āļŦāļĢāļ·āļ­āļœāđˆāļēāļ™ Firebase console Firestore āļˆāļ°āļšāļąāļ™āļ—āļķāļāļĨāļīāļ‡āļāđŒāđ‚āļ”āļĒāļ•āļĢāļ‡āđ€āļžāļ·āđˆāļ­āļŠāļĢāđ‰āļēāļ‡ index āļ—āļĩāđˆāļ‚āļēāļ”āļŦāļēāļĒāđ„āļ›āđ€āļĄāļ·āđˆāļ­ query āļĨāđ‰āļĄāđ€āļŦāļĨāļ§

āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāđ€āļ•āļĢāļĩāļĒāļĄāļ•āļąāļ§āļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Flutter āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ āđ‚āļĄāļ”āļđāļĨāļāļķāļāļāļ™āđ€āļ‰āļžāļēāļ°āļ—āļēāļ‡āļ„āļĢāļ­āļšāļ„āļĨāļļāļĄāļŦāļąāļ§āļ‚āđ‰āļ­āđ€āļŦāļĨāđˆāļēāļ™āļĩāđ‰āļ”āđ‰āļ§āļĒāđāļšāļšāļ—āļ”āļŠāļ­āļšāđ€āļŠāļīāļ‡āđ‚āļ•āđ‰āļ•āļ­āļšāđāļĨāļ°āļ„āļ§āļēāļĄāļ—āđ‰āļēāļ—āļēāļĒāđāļšāļšāļˆāļąāļšāđ€āļ§āļĨāļē

āđ€āļĢāļīāđˆāļĄāļāļķāļāļ‹āđ‰āļ­āļĄāđ€āļĨāļĒ!

āļ—āļ”āļŠāļ­āļšāļ„āļ§āļēāļĄāļĢāļđāđ‰āļ‚āļ­āļ‡āļ„āļļāļ“āļ”āđ‰āļ§āļĒāļ•āļąāļ§āļˆāļģāļĨāļ­āļ‡āļŠāļąāļĄāļ āļēāļĐāļ“āđŒāđāļĨāļ°āđāļšāļšāļ—āļ”āļŠāļ­āļšāđ€āļ—āļ„āļ™āļīāļ„āļ„āļĢāļąāļš

āļšāļ—āļŠāļĢāļļāļ›

  • FlutterFire SDK v4.15 āļĄāļēāļžāļĢāđ‰āļ­āļĄāđāļžāđ‡āļāđ€āļāļˆāļ—āļĩāđˆāđ€āļŠāļ–āļĩāļĒāļĢāļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™ (v6.1.2) āđāļĨāļ° Firestore (v6.4.1) āļžāļĢāđ‰āļ­āļĄāļŸāļĩāđ€āļˆāļ­āļĢāđŒāđƒāļŦāļĄāđˆāļ­āļĒāđˆāļēāļ‡ Firestore Pipelines āđāļĨāļ°āļāļēāļĢāļ•āļĢāļ§āļˆāļŠāļ­āļšāļ™āđ‚āļĒāļšāļēāļĒāļĢāļŦāļąāļŠāļœāđˆāļēāļ™
  • authStateChanges() āļĄāļ­āļšāļŠāļ•āļĢāļĩāļĄāđāļšāļš reactive āļŠāļģāļŦāļĢāļąāļšāļˆāļąāļ”āļāļēāļĢāļŠāļ–āļēāļ™āļ°āļāļēāļĢāđ€āļ‚āđ‰āļēāļŠāļđāđˆāļĢāļ°āļšāļšāļ—āļąāđˆāļ§āļ—āļąāđ‰āļ‡āđāļ­āļ›āđ‚āļ”āļĒāđ„āļĄāđˆāļ•āđ‰āļ­āļ‡āļ•āļĢāļ§āļˆāļŠāļ­āļšāļ”āđ‰āļ§āļĒāļ•āļ™āđ€āļ­āļ‡
  • āļāļēāļĢāļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢ CRUD āļ‚āļ­āļ‡ Firestore āđ€āļ›āđ‡āļ™āđ„āļ›āļ•āļēāļĄāļĢāļđāļ›āđāļšāļšāļ—āļĩāđˆāđ€āļĢāļĩāļĒāļšāļ‡āđˆāļēāļĒ: add, get, update, delete āļšāļ™āļāļēāļĢāļ­āđ‰āļēāļ‡āļ­āļīāļ‡ collection āđāļĨāļ° document
  • āļāļēāļĢāļ‹āļīāļ‡āđ‚āļ„āļĢāđ„āļ™āļ‹āđŒāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒāļœāđˆāļēāļ™ snapshots() āļ‚āļˆāļąāļ”āļāļēāļĢ polling āđāļĨāļ°āļœāļŠāļēāļ™āļĢāļ§āļĄāđ‚āļ”āļĒāļ•āļĢāļ‡āļāļąāļš StreamBuilder āđ€āļžāļ·āđˆāļ­āļāļēāļĢāļ­āļąāļ›āđ€āļ”āļ• UI āđ‚āļ”āļĒāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļī
  • āļāļŽāļ„āļ§āļēāļĄāļ›āļĨāļ­āļ”āļ āļąāļĒāđ€āļ›āđ‡āļ™āļŠāļīāđˆāļ‡āļˆāļģāđ€āļ›āđ‡āļ™āļŠāļģāļŦāļĢāļąāļš production āļ„āļ§āļĢāļ•āļĢāļ§āļˆāļŠāļ­āļš request.auth.uid āđ€āļ—āļĩāļĒāļšāļāļąāļšāļŸāļīāļĨāļ”āđŒāļ„āļ§āļēāļĄāđ€āļ›āđ‡āļ™āđ€āļˆāđ‰āļēāļ‚āļ­āļ‡āļ‚āļ­āļ‡ document āđ€āļŠāļĄāļ­
  • āļāļēāļĢāļ„āļ‡āļ­āļĒāļđāđˆāđāļšāļšāļ­āļ­āļŸāđ„āļĨāļ™āđŒāļ—āļģāļ‡āļēāļ™āļ­āļĒāđˆāļēāļ‡āđ‚āļ›āļĢāđˆāļ‡āđƒāļŠāļšāļ™āļĄāļ·āļ­āļ–āļ·āļ­ āđƒāļŠāđ‰ hasPendingWrites āđ€āļžāļ·āđˆāļ­āļŠāļ·āđˆāļ­āļŠāļēāļĢāļŠāļ–āļēāļ™āļ°āļāļēāļĢāļ‹āļīāļ‡āļ„āđŒāđƒāļŦāđ‰āļœāļđāđ‰āđƒāļŠāđ‰āļ—āļĢāļēāļš
  • āļĢāļđāļ›āđāļšāļš repository āđāļĒāļ Firebase āļ­āļ­āļāļˆāļēāļāļ•āļĢāļĢāļāļ°āļ—āļēāļ‡āļ˜āļļāļĢāļāļīāļˆ āļ—āļģāđƒāļŦāđ‰āļāļēāļĢāļ—āļ”āļŠāļ­āļšāđāļĨāļ°āļāļēāļĢāļĒāđ‰āļēāļĒāđƒāļ™āļ­āļ™āļēāļ„āļ•āđ€āļ›āđ‡āļ™āđ€āļĢāļ·āđˆāļ­āļ‡āļ‡āđˆāļēāļĒ
  • āļāļēāļĢāđ€āļ•āļĢāļĩāļĒāļĄāļ•āļąāļ§āļŠāļąāļĄāļ āļēāļĐāļ“āđŒāļ„āļ§āļĢāļ„āļĢāļ­āļšāļ„āļĨāļļāļĄāļ„āļ§āļēāļĄāđāļ•āļāļ•āđˆāļēāļ‡āļ‚āļ­āļ‡āļŠāļ•āļĢāļĩāļĄ auth, āļžāļĪāļ•āļīāļāļĢāļĢāļĄāļ­āļ­āļŸāđ„āļĨāļ™āđŒ, āļĢāļđāļ›āđāļšāļšāļāļēāļĢāļŠāļĢāđ‰āļēāļ‡āđāļšāļšāļˆāļģāļĨāļ­āļ‡āļ‚āđ‰āļ­āļĄāļđāļĨ āđāļĨāļ°āļ‚āđ‰āļ­āļāļģāļŦāļ™āļ”āļ‚āļ­āļ‡ composite index

āđ€āļĢāļīāđˆāļĄāļāļķāļāļ‹āđ‰āļ­āļĄāđ€āļĨāļĒ!

āļ—āļ”āļŠāļ­āļšāļ„āļ§āļēāļĄāļĢāļđāđ‰āļ‚āļ­āļ‡āļ„āļļāļ“āļ”āđ‰āļ§āļĒāļ•āļąāļ§āļˆāļģāļĨāļ­āļ‡āļŠāļąāļĄāļ āļēāļĐāļ“āđŒāđāļĨāļ°āđāļšāļšāļ—āļ”āļŠāļ­āļšāđ€āļ—āļ„āļ™āļīāļ„āļ„āļĢāļąāļš

āđāļ—āđ‡āļ

#flutter
#firebase
#authentication
#firestore
#dart
#mobile development

āđāļŠāļĢāđŒ

āļšāļ—āļ„āļ§āļēāļĄāļ—āļĩāđˆāđ€āļāļĩāđˆāļĒāļ§āļ‚āđ‰āļ­āļ‡

āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒāļ‡āļēāļ™ Flutter āļŠāļģāļŦāļĢāļąāļšāļ™āļąāļāļžāļąāļ’āļ™āļēāđāļ­āļ›āļĄāļ·āļ­āļ–āļ·āļ­

20 āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒāļ‡āļēāļ™ Flutter āļ—āļĩāđˆāļžāļšāļšāđˆāļ­āļĒāļ—āļĩāđˆāļŠāļļāļ”āļŠāļģāļŦāļĢāļąāļšāļ™āļąāļāļžāļąāļ’āļ™āļēāđāļ­āļ›āļĄāļ·āļ­āļ–āļ·āļ­

āđ€āļ•āļĢāļĩāļĒāļĄāļ•āļąāļ§āļŠāļąāļĄāļ āļēāļĐāļ“āđŒāļ‡āļēāļ™ Flutter āļ”āđ‰āļ§āļĒāļ„āļģāļ–āļēāļĄ 20 āļ‚āđ‰āļ­āļ—āļĩāđˆāļ–āļđāļāļ–āļēāļĄāļšāđˆāļ­āļĒāļ—āļĩāđˆāļŠāļļāļ” āļ„āļĢāļ­āļšāļ„āļĨāļļāļĄ Widget, State Management, Dart, āļŠāļ–āļēāļ›āļąāļ•āļĒāļāļĢāļĢāļĄ āđāļĨāļ°āđāļ™āļ§āļ—āļēāļ‡āļ›āļāļīāļšāļąāļ•āļīāļ—āļĩāđˆāļ”āļĩāļ—āļĩāđˆāļŠāļļāļ” āļžāļĢāđ‰āļ­āļĄāļ„āļģāļ­āļ˜āļīāļšāļēāļĒāļ­āļĒāđˆāļēāļ‡āļĨāļ°āđ€āļ­āļĩāļĒāļ”āđāļĨāļ°āļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡āđ‚āļ„āđ‰āļ”

āļ„āļđāđˆāļĄāļ·āļ­āļāļēāļĢāļŠāļĢāđ‰āļēāļ‡āđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™āļĄāļ·āļ­āļ–āļ·āļ­āļ•āļąāļ§āđāļĢāļāļ”āđ‰āļ§āļĒ Flutter āđāļĨāļ° Dart

Flutter: āļŠāļĢāđ‰āļēāļ‡āđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™āļ‚āđ‰āļēāļĄāđāļžāļĨāļ•āļŸāļ­āļĢāđŒāļĄāļ•āļąāļ§āđāļĢāļ

āļ„āļđāđˆāļĄāļ·āļ­āļ‰āļšāļąāļšāļŠāļĄāļšāļđāļĢāļ“āđŒāļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļŠāļĢāđ‰āļēāļ‡āđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™āļĄāļ·āļ­āļ–āļ·āļ­āļ‚āđ‰āļēāļĄāđāļžāļĨāļ•āļŸāļ­āļĢāđŒāļĄāļ”āđ‰āļ§āļĒ Flutter āđāļĨāļ° Dart āļ„āļĢāļ­āļšāļ„āļĨāļļāļĄ Widget āļāļēāļĢāļˆāļąāļ”āļāļēāļĢāļŠāļ–āļēāļ™āļ° āļāļēāļĢāļ™āļģāļ—āļēāļ‡ āđāļĨāļ°āđāļ™āļ§āļ—āļēāļ‡āļ›āļāļīāļšāļąāļ•āļīāļ—āļĩāđˆāļ”āļĩāļŠāļģāļŦāļĢāļąāļšāļœāļđāđ‰āđ€āļĢāļīāđˆāļĄāļ•āđ‰āļ™

āļāļēāļĢāđ€āļ›āļĢāļĩāļĒāļšāđ€āļ—āļĩāļĒāļš Riverpod āđāļĨāļ° BLoC āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļˆāļąāļ”āļāļēāļĢ state āđƒāļ™ Flutter

āļāļēāļĢāļˆāļąāļ”āļāļēāļĢ State āđƒāļ™ Flutter: Riverpod vs BLoC - āļ„āļđāđˆāļĄāļ·āļ­āđ€āļ›āļĢāļĩāļĒāļšāđ€āļ—āļĩāļĒāļšāļ‰āļšāļąāļšāļŠāļĄāļšāļđāļĢāļ“āđŒ

āļāļēāļĢāđ€āļ›āļĢāļĩāļĒāļšāđ€āļ—āļĩāļĒāļšāđ€āļŠāļīāļ‡āļĨāļķāļāļĢāļ°āļŦāļ§āđˆāļēāļ‡ Riverpod āđāļĨāļ° BLoC āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļˆāļąāļ”āļāļēāļĢ state āđƒāļ™ Flutter āļŠāļ–āļēāļ›āļąāļ•āļĒāļāļĢāļĢāļĄ āļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļž āļ„āļ§āļēāļĄāļŠāļēāļĄāļēāļĢāļ–āđƒāļ™āļāļēāļĢāļ—āļ”āļŠāļ­āļš āđāļĨāļ°āļāļĢāļ“āļĩāļāļēāļĢāđƒāļŠāđ‰āļ‡āļēāļ™āđ€āļžāļ·āđˆāļ­āđ€āļĨāļ·āļ­āļāđ‚āļ‹āļĨāļđāļŠāļąāļ™āļ—āļĩāđˆāļ”āļĩāļ—āļĩāđˆāļŠāļļāļ”