Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce geliştirme ortamınızın 2026 yılı standartlarına uygun olduğundan emin olmalısınız. Flutter SDK sürümünüzün en az 3.24 ve üzeri olması, performanslı bir geliştirme süreci için kritiktir.
- Flutter SDK: 3.24.0 veya daha yeni bir sürüm.
- IDE: VS Code veya Android Studio (güncel eklentileriyle).
- Firebase Hesabı: Projenizi bağlamak için bir Firebase konsol hesabı.
- Bağımlılıklar:
cloud_firestore(veritabanı),firebase_auth(kimlik doğrulama) veprovider(durum yönetimi).
Projenizi oluşturduktan sonra pubspec.yaml dosyanıza şu bağımlılıkları ekleyerek işe başlayın:
dependencies:
flutter:
sdk: flutter
firebase_core: ^3.0.0
cloud_firestore: ^5.0.0
firebase_auth: ^5.0.0
provider: ^6.1.0
intl: ^0.19.0
Adım Adım Firebase ile Veri Modeli Tasarımı
Çoklu cihaz senkronizasyonu için veritabanı yapınızın hiyerarşik ve esnek olması gerekir. Firebase Firestore, NoSQL yapısı sayesinde ajanda verilerini "koleksiyonlar" ve "dokümanlar" şeklinde saklamak için idealdir.
Aşağıdaki örnekte, bir ajanda etkinliğinin veri yapısını tanımlayan Dart sınıfını görebilirsiniz:
class AgendaEvent {
final String id;
final String title;
final DateTime dateTime;
final String userId;
AgendaEvent({required this.id, required this.title, required this.dateTime, required this.userId});
Map toMap() {
return {
'title': title,
'dateTime': dateTime.toIso8601String(),
'userId': userId,
};
}
}
Bu sınıf, verilerin Firestore'a yazılmadan önce doğrulanmasını sağlar. userId alanı, verinin hangi kullanıcıya ait olduğunu belirleyerek güvenlik kuralları (Security Rules) ile erişim kontrolü yapmamıza olanak tanır.
Gerçek Zamanlı Senkronizasyon ve Veri Okuma
Flutter'da StreamBuilder kullanarak, veritabanındaki değişiklikleri anlık olarak arayüzde yansıtabiliriz. Bir cihazda eklenen etkinlik, diğer cihazlarda saniyeler içinde görünür hale gelir.
Stream getEvents() {
return FirebaseFirestore.instance
.collection('events')
.where('userId', isEqualTo: currentUser.uid)
.snapshots()
.map((snapshot) => snapshot.docs.map((doc) => AgendaEvent.fromMap(doc.data())).toList());
}
Bu kod bloğu, Firestore üzerindeki etkinlikler koleksiyonunu sürekli dinler. Veri tabanında bir değişiklik olduğunda (ekleme, silme, güncelleme), arayüz otomatik olarak yeniden tetiklenir.
Güvenlik Kuralları ve Veri İzolasyonu
Kritik Uyarı: Firebase veritabanı kurallarınızı asla "public" bırakmayın. Her kullanıcı, sadece kendi oluşturduğu veriye erişebilmeli ve sadece kendi verisini değiştirebilmelidir. Üretim ortamında (production) mutlaka Firestore Security Rules kısmında
request.auth.uid == resource.data.userIdkontrolünü sağlayın.
Firestore kurallarınız şu şekilde yapılandırılmalıdır:
service cloud.firestore {
match /databases/{database}/documents {
match /events/{event} {
allow read, write: if request.auth != null && request.auth.uid == resource.data.userId;
}
}
}
State Management ile Arayüz Yönetimi
Uygulamanın karmaşıklığı arttıkça, veriyi yönetmek için Provider veya Riverpod gibi kütüphaneler kullanmak zorunludur. Aşağıda, ajanda verilerini merkezi bir noktadan yöneten bir ChangeNotifier örneği bulunmaktadır:
class EventProvider extends ChangeNotifier {
List _events = [];
List get events => _events;
void addEvent(AgendaEvent event) {
FirebaseFirestore.instance.collection('events').add(event.toMap());
notifyListeners();
}
}
Bu yapı, uygulama genelinde verilerin tutarlı kalmasını sağlar ve gereksiz ağ isteklerini engellemek için önbellekleme (caching) mekanizmalarını kolaylaştırır.
Çoklu Cihaz Paylaşımı ve Karşılaştırma
Mobil ajanda uygulamalarında veri senkronizasyonu için tercih edilebilecek yöntemleri aşağıda karşılaştırdık:
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Firebase Firestore | Gerçek zamanlı, kurulumu kolay | Yüksek ölçekte maliyetli olabilir |
| Supabase (PostgreSQL) | İlişkisel veritabanı, SQL desteği | Öğrenme eğrisi daha dik |
| Local SQLite + API | Tam kontrol, düşük maliyet | Senkronizasyon mantığı karmaşık |
Sıkça Sorulan Sorular
Uygulama çevrimdışı iken veri eklersem ne olur?
Firestore, yerel bir önbellek (cache) kullanır. İnternet bağlantısı koptuğunda veriler yerel cihazda saklanır ve cihaz tekrar çevrimiçi olduğunda otomatik olarak bulut ile senkronize edilir.
Birden fazla kullanıcı aynı ajandayı paylaşabilir mi?
Evet, Firestore'da etkinlik dokümanlarına bir "sharedWith" listesi ekleyerek ve güvenlik kurallarında bu listeyi kontrol ederek çoklu kullanıcı erişimi sağlayabilirsiniz.
Verilerim ne kadar güvenli?
Firebase, endüstri standardı olan AES-256 şifreleme kullanır. Ancak, uygulama tarafında hassas verileri şifrelemek için flutter_secure_storage paketini kullanmanızı öneririz.
Performans için nelere dikkat etmeliyim?
Sonsuz listeler (infinite lists) için ListView.builder kullanmalı ve veritabanı sorgularınızda mutlaka index (indeks) oluşturmalısınız.
Farklı saat dilimleri sorun yaratır mı?
Evet, her zaman UTC zaman damgalarını (timestamp) saklayın ve kullanıcı arayüzünde intl kütüphanesini kullanarak yerel saate dönüştürün.
İleri Düzey Hata Ayıklama ve Performans Optimizasyonu
Çoklu cihaz senkronizasyonu yapan uygulamalarda, özellikle ağ kesintileri veya eşzamanlı veri yazma işlemlerinde beklenmedik durumlar oluşabilir. Uygulamanızın kararlılığını artırmak için Firebase'in sunduğu hata ayıklama araçlarını ve Flutter'ın performans profilleme özelliklerini etkin bir şekilde kullanmalısınız.
Firestore İşlemlerinde Hata Yönetimi
Veri yazma veya okuma işlemleri sırasında oluşabilecek ağ hatalarını yakalamak için try-catch bloklarını FirebaseException ile özelleştirin. Bu, kullanıcıya sadece "hata oluştu" demek yerine, sorunun kaynağını (örn: yetki eksikliği veya ağ zaman aşımı) belirtmenizi sağlar.
Future updateEvent(String eventId, Map data) async {
try {
await FirebaseFirestore.instance.collection('events').doc(eventId).update(data);
} on FirebaseException catch (e) {
debugPrint("Firestore Hatası: ${e.code} - ${e.message}");
// Kullanıcıya uygun bir uyarı gösterin
rethrow;
} catch (e) {
debugPrint("Genel Hata: $e");
}
}
Render Performansını Artırma
Ajanda uygulamalarında liste öğeleri (ListView) çok fazla veri içerdiğinde, her bir öğenin yeniden oluşturulması (rebuild) performans kaybına yol açar. ListView.builder kullanırken const anahtar kelimesini stratejik olarak kullanmak ve RepaintBoundary ile widget ağacını izole etmek, FPS düşüşlerini engeller.
Uygulama Dağıtımı ve Ölçeklendirme Stratejileri
Uygulamanızı canlıya almadan önce, Firebase projenizin "Production" moduna geçtiğinden emin olmalısınız. Ayrıca, çoklu cihaz senkronizasyonunda veri çakışmalarını (conflict resolution) yönetmek için Firestore'un sunduğu FieldValue.serverTimestamp() metodunu kullanmak, sunucu saatini referans alarak tutarlılığı sağlar.
Firebase İndeksleme (Indexing)
Uygulamanızda tarih bazlı sıralama veya filtreleme yapıyorsanız, Firestore konsolu üzerinden bileşik indeksler oluşturmanız gerekir. Aksi takdirde, sorgularınız büyük veri setlerinde hata verecektir. İndeksleme gerektiren bir sorgu örneği aşağıdadır:
// Tarihe göre sıralanmış ve belirli bir kullanıcıya ait etkinlikleri getirme
FirebaseFirestore.instance
.collection('events')
.where('userId', isEqualTo: currentUserId)
.orderBy('eventDate', descending: true)
.snapshots();
Ölçeklenebilirlik İçin İpuçları
- Pagination (Sayfalandırma): Tüm veriyi tek seferde çekmek yerine
limit()vestartAfterDocument()kullanarak verileri parçalar halinde yükleyin. - Local Caching: Firestore'un yerel önbellekleme özelliğini açık tutarak, kullanıcının interneti olmasa bile ajandasına erişebilmesini sağlayın.
- Cloud Functions: Karmaşık hesaplamaları (örneğin aylık etkinlik istatistikleri) cihaz üzerinde değil, Firebase Cloud Functions kullanarak sunucu tarafında yapın.
Profesyonel Not: Uygulamanızın ölçeklenmesi durumunda, Firestore okuma/yazma maliyetlerini düşürmek içinsnapshot listeneryerine, verinin nadir değiştiği durumlardaget()metodunu tercih ederek gereksiz ağ trafiğini engelleyebilirsiniz.
Sonuç
Flutter ile çoklu cihaz paylaşımlı bir ajanda geliştirmek, doğru mimari kararlar alındığında oldukça sürdürülebilir bir süreçtir. Firebase Firestore'un gerçek zamanlı yetenekleri, Flutter'ın reaktif arayüz yapısı ile birleştiğinde, profesyonel düzeyde bir mobil deneyim sunar. Bir sonraki adım olarak, uygulamanıza local_auth paketi ile biyometrik giriş özelliği ekleyerek güvenliği bir üst seviyeye taşıyabilirsiniz.
Yasal Uyarı ve Güvenlik Sorumluluğu: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Uygulamanızda kullanıcı verilerini işlerken KVKK ve GDPR uyumluluğunu sağlamak, verileri şifrelemek ve güvenlik açıklarına karşı düzenli sızma testleri yapmak geliştiricinin sorumluluğundadır.


Yorumlar (0)
Yorum Yaz