Flutter'da Firebase Entegrasyonu: Auth, Firestore ve Storage
Firebase, Flutter'ın en yaygın kullanılan backend çözümüdür. Authentication, gerçek zamanlı veritabanı, dosya depolama ve push bildirim gibi hazır servisleriyle arka uç geliştirme ihtiyacını büyük ölçüde azaltır.
Kurulum
# FlutterFire CLI ile yapılandırma
dart pub global activate flutterfire_cli
flutterfire configure --project=benim-projem
# pubspec.yaml
# firebase_core: ^3.3.0
# firebase_auth: ^5.1.4
# cloud_firestore: ^5.2.1
# firebase_storage: ^12.1.3
// main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const UygulamaWidget());
}
Firebase Authentication
class AuthServis {
final FirebaseAuth _auth = FirebaseAuth.instance;
// Kullanıcı oturumu akışı
Stream<User?> get kullanicıAkisi => _auth.authStateChanges();
// E-posta ile kayıt
Future<UserCredential> kayitOl({
required String email,
required String sifre,
required String isim,
}) async {
final credential = await _auth.createUserWithEmailAndPassword(
email: email,
password: sifre,
);
await credential.user?.updateDisplayName(isim);
await credential.user?.sendEmailVerification();
return credential;
}
// E-posta ile giriş
Future<UserCredential> girisYap(String email, String sifre) =>
_auth.signInWithEmailAndPassword(email: email, password: sifre);
// Google ile giriş
Future<UserCredential> googleIleGiris() 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);
}
// Şifre sıfırlama
Future<void> sifreSifirla(String email) =>
_auth.sendPasswordResetEmail(email: email);
Future<void> cikisYap() => _auth.signOut();
User? get mevcutKullanici => _auth.currentUser;
}
Auth ile Korunan Rotalar
class AuthGateway extends StatelessWidget {
const AuthGateway({super.key});
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Scaffold(body: Center(child: CircularProgressIndicator()));
}
return snapshot.hasData ? const AnaSayfa() : const GirisSayfasi();
},
);
}
}
Cloud Firestore CRUD
class GonderiDepo {
final _koleksiyon = FirebaseFirestore.instance.collection("gonderiler");
// Oluştur
Future<DocumentReference> gonderiOlustur(Gonderi gonderi) =>
_koleksiyon.add(gonderi.toJson());
// Oku - tek döküman
Future<Gonderi?> gonderiGetir(String id) async {
final doc = await _koleksiyon.doc(id).get();
return doc.exists ? Gonderi.fromJson(doc.data()!, doc.id) : null;
}
// Gerçek zamanlı liste dinle
Stream<List<Gonderi>> gonderileriDinle(String kullaniciId) =>
_koleksiyon
.where("kullaniciId", isEqualTo: kullaniciId)
.orderBy("olusturulmaZamani", descending: true)
.limit(20)
.snapshots()
.map((snap) => snap.docs
.map((d) => Gonderi.fromJson(d.data(), d.id))
.toList());
// Güncelle
Future<void> gonderiGuncelle(String id, Map<String, dynamic> guncellemeler) =>
_koleksiyon.doc(id).update({
...guncellemeler,
"guncellenmeZamani": FieldValue.serverTimestamp(),
});
// Sil
Future<void> gonderiSil(String id) => _koleksiyon.doc(id).delete();
// Toplu işlem
Future<void> topluGuncelle(List<String> idler, Map<String, dynamic> degerler) async {
final batch = FirebaseFirestore.instance.batch();
for (final id in idler) {
batch.update(_koleksiyon.doc(id), degerler);
}
await batch.commit();
}
}
Firebase Storage — Dosya Yükleme
class DepolamaServis {
final _storage = FirebaseStorage.instance;
Future<String> resimYukle({
required String kullaniciId,
required Uint8List bytes,
required String uzanti,
}) async {
final ref = _storage.ref("profil//avatar.");
final gorev = ref.putData(
bytes,
SettableMetadata(contentType: "image/"),
);
// İlerleme takibi
gorev.snapshotEvents.listen((snapshot) {
final yuzde = snapshot.bytesTransferred / snapshot.totalBytes * 100;
print("Yükleniyor: %");
});
await gorev;
return ref.getDownloadURL();
}
Future<void> dosyaSil(String url) async {
final ref = _storage.refFromURL(url);
await ref.delete();
}
}
// image_picker ile kullanım
Future<void> profilResmiGuncelle() async {
final picker = ImagePicker();
final secilen = await picker.pickImage(
source: ImageSource.gallery,
maxWidth: 512,
maxHeight: 512,
imageQuality: 85,
);
if (secilen == null) return;
final bytes = await secilen.readAsBytes();
final uzanti = secilen.path.split(".").last;
final url = await DepolamaServis().resimYukle(
kullaniciId: AuthServis().mevcutKullanici!.uid,
bytes: bytes,
uzanti: uzanti,
);
await FirebaseAuth.instance.currentUser?.updatePhotoURL(url);
}
Firestore Güvenlik Kuralları
// firestore.rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Kullanıcı kendi verisine erişebilir
match /kullanicilar/{userId} {
allow read: if request.auth != null;
allow write: if request.auth.uid == userId;
}
// Gönderiler: herkes okuyabilir, sadece sahip düzenleyebilir
match /gonderiler/{gonderiId} {
allow read: if true;
allow create: if request.auth != null
&& request.resource.data.kullaniciId == request.auth.uid;
allow update, delete: if request.auth.uid == resource.data.kullaniciId;
}
}
}
Offline Destek
// Firestore offline önbelleği etkinleştir
FirebaseFirestore.instance.settings = const Settings(
persistenceEnabled: true,
cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED,
);
Sonuç
Firebase, Flutter uygulamalarına hızla backend kapasitesi kazandırır. Authentication ile güvenli giriş, Firestore ile gerçek zamanlı veri ve Storage ile dosya yönetimi üçlüsü çoğu uygulama için yeterlidir. Güvenlik kurallarını ihmal etmeyin — production'da her koleksiyon için kural tanımlamak zorunludur.