(İsteğe bağlı) Firebase Emulator Suite ile prototip oluşturun ve test edin
Uygulamanızın Realtime Database'den okuma ve Realtime Database'e nasıl yazdığı hakkında konuşmadan önce, Realtime Database işlevselliğini prototiplemek ve test etmek için kullanabileceğiniz bir dizi aracı tanıtalım: Firebase Emulator Suite. Farklı veri modelleri deniyor, güvenlik kurallarınızı optimize ediyor veya arka uçla etkileşim kurmanın en uygun maliyetli yolunu bulmaya çalışıyorsanız, canlı hizmetleri dağıtmadan yerel olarak çalışabilmek harika bir fikir olabilir.
Gerçek Zamanlı Veritabanı öykünücüsü, uygulamanızın öykünülmüş veritabanı içeriğiniz ve yapılandırmanızın yanı sıra isteğe bağlı olarak öykünmüş proje kaynaklarınızla (işlevler, diğer veritabanları ve güvenlik kuralları) etkileşime girmesini sağlayan Emulator Suite'in bir parçasıdır.emulator_suite_short
Gerçek Zamanlı Veritabanı öykünücüsünü kullanmak yalnızca birkaç adımı içerir:
- Öykünücüye bağlanmak için uygulamanızın test yapılandırmasına bir kod satırı ekleme.
- Yerel proje dizininizin kökünden, çalıştırılan
firebase emulators:start
. - Her zamanki gibi bir Realtime Database platformu SDK'sı veya Realtime Database REST API kullanarak uygulamanızın prototip kodundan çağrı yapma.
Gerçek Zamanlı Veritabanı ve Bulut İşlevlerini içeren ayrıntılı bir kılavuz mevcuttur. Emulator Suite tanıtımına da bir göz atmalısınız.
Veritabanı Referansı Alın
Veritabanından veri okumak veya yazmak için bir DatabaseReference
örneğine ihtiyacınız vardır:
DatabaseReference ref = FirebaseDatabase.instance.ref();
Veri yaz
Bu belge, Firebase verilerini okuma ve yazmanın temellerini kapsar.
Firebase verileri bir DatabaseReference
yazılır ve referans tarafından yayılan olaylar beklenerek veya dinlenerek alınır. Olaylar, verilerin ilk durumu için bir kez ve veriler değiştiğinde tekrar yayınlanır.
Temel yazma işlemleri
Temel yazma işlemleri için, verileri belirtilen bir referansa kaydetmek ve bu yoldaki mevcut verileri değiştirmek için set()
kullanabilirsiniz. Şu türlere bir başvuru ayarlayabilirsiniz: String
, boolean
, int
, double
, Map
, List
.
Örneğin, set()
ile bir kullanıcıyı aşağıdaki gibi ekleyebilirsiniz:
DatabaseReference ref = FirebaseDatabase.instance.ref("users/123");
await ref.set({
"name": "John",
"age": 18,
"address": {
"line1": "100 Mountain View"
}
});
set()
bu şekilde kullanılması, tüm alt düğümler de dahil olmak üzere belirtilen konumdaki verilerin üzerine yazar. Ancak yine de tüm nesneyi yeniden yazmadan bir çocuğu güncelleyebilirsiniz. Kullanıcıların profillerini güncellemelerine izin vermek istiyorsanız, kullanıcı adını aşağıdaki gibi güncelleyebilirsiniz:
DatabaseReference ref = FirebaseDatabase.instance.ref("users/123");
// Only update the name, leave the age and address!
await ref.update({
"age": 19,
});
update()
yöntemi, düğümlere giden bir alt yolu kabul ederek veritabanındaki birden çok düğümü aynı anda güncellemenize olanak tanır:
DatabaseReference ref = FirebaseDatabase.instance.ref("users");
await ref.update({
"123/age": 19,
"123/address/line1": "1 Mountain View",
});
Verileri oku
Değer olaylarını dinleyerek verileri okuyun
Bir yoldaki verileri okumak ve değişiklikleri dinlemek için, DatabaseEvent
s dinlemek için DatabaseReference
öğesinin onValue
özelliğini kullanın.
Belirli bir yoldaki verileri, olay sırasında var olduğu şekliyle okumak için DatabaseEvent
kullanabilirsiniz. Bu olay, dinleyici eklendiğinde bir kez ve alt öğeler de dahil olmak üzere veriler her değiştiğinde tetiklenir. Olay, alt veriler de dahil olmak üzere o konumdaki tüm verileri içeren bir snapshot
özelliğine sahiptir. Veri yoksa, anlık görüntünün exists
özelliği false
, value
özelliği boş olacaktır.
Aşağıdaki örnek, bir gönderinin ayrıntılarını veritabanından alan bir sosyal blog uygulamasını göstermektedir:
DatabaseReference starCountRef =
FirebaseDatabase.instance.ref('posts/$postId/starCount');
starCountRef.onValue.listen((DatabaseEvent event) {
final data = event.snapshot.value;
updateStarCount(data);
});
Dinleyici, value
özelliğinde olay anında veritabanında belirtilen konumdaki verileri içeren bir DataSnapshot
alır.
Verileri bir kez oku
get() kullanarak bir kez okuyun
SDK, uygulamanız ister çevrimiçi ister çevrimdışı olsun, veritabanı sunucularıyla etkileşimleri yönetmek için tasarlanmıştır.
Genel olarak, arka uçtan veri güncellemelerinden haberdar olmak için verileri okumak üzere yukarıda açıklanan değer olayları tekniklerini kullanmalısınız. Bu teknikler, kullanımınızı ve faturalandırmanızı azaltır ve kullanıcılarınıza çevrimiçi ve çevrimdışı olduklarında en iyi deneyimi sunmak için optimize edilmiştir.
Verilere yalnızca bir kez ihtiyacınız varsa, veritabanından verilerin anlık görüntüsünü almak için get()
kullanabilirsiniz. Herhangi bir nedenle get()
sunucu değerini döndüremezse, müşteri yerel depolama önbelleğini inceler ve değer hala bulunamazsa bir hata döndürür.
Aşağıdaki örnek, bir kullanıcının herkese açık kullanıcı adının veritabanından tek seferde alındığını gösterir:
final ref = FirebaseDatabase.instance.ref();
final snapshot = await ref.child('users/$userId').get();
if (snapshot.exists) {
print(snapshot.value);
} else {
print('No data available.');
}
Gereksiz get()
kullanımı, bant genişliği kullanımını artırabilir ve yukarıda gösterildiği gibi gerçek zamanlı bir dinleyici kullanılarak önlenebilecek performans kaybına neden olabilir.
Once() ile verileri bir kez okuyun
Bazı durumlarda, sunucuda güncellenmiş bir değer olup olmadığını kontrol etmek yerine, yerel önbellekten gelen değerin hemen döndürülmesini isteyebilirsiniz. Bu durumlarda, verileri yerel disk önbelleğinden hemen almak için once()
öğesini kullanabilirsiniz.
Bu, yalnızca bir kez yüklenmesi gereken ve sık sık değişmesi veya aktif dinleme gerektirmesi beklenmeyen veriler için kullanışlıdır. Örneğin, önceki örneklerde yer alan blog uygulaması, yeni bir gönderi yazmaya başladıklarında bir kullanıcının profilini yüklemek için bu yöntemi kullanır:
final event = await ref.once(DatabaseEventType.value);
final username = event.snapshot.value?.username ?? 'Anonymous';
Verileri güncelleme veya silme
Belirli alanları güncelle
Diğer alt düğümlerin üzerine yazmadan aynı anda bir düğümün belirli alt öğelerine yazmak için update()
yöntemini kullanın.
update()
öğesini çağırırken, anahtar için bir yol belirterek alt düzey alt değerleri güncelleyebilirsiniz. Veriler daha iyi ölçeklendirmek için birden çok konumda depolanıyorsa, veri yayma özelliğini kullanarak bu verilerin tüm örneklerini güncelleyebilirsiniz. Örneğin, bir sosyal blog uygulaması bir gönderi oluşturmak ve aynı anda bunu en son etkinlik akışına ve gönderen kullanıcının etkinlik akışına güncellemek isteyebilir. Bunu yapmak için, blog uygulaması şuna benzer bir kod kullanır:
void writeNewPost(String uid, String username, String picture, String title,
String body) async {
// A post entry.
final postData = {
'author': username,
'uid': uid,
'body': body,
'title': title,
'starCount': 0,
'authorPic': picture,
};
// Get a key for a new Post.
final newPostKey =
FirebaseDatabase.instance.ref().child('posts').push().key;
// Write the new post's data simultaneously in the posts list and the
// user's post list.
final Map<String, Map> updates = {};
updates['/posts/$newPostKey'] = postData;
updates['/user-posts/$uid/$newPostKey'] = postData;
return FirebaseDatabase.instance.ref().update(updates);
}
Bu örnek /posts/$postid
adresindeki tüm kullanıcılar için gönderileri içeren düğümde bir gönderi oluşturmak ve aynı anda key
ile anahtarı almak için push()
u kullanır. Anahtar daha sonra kullanıcının /user-posts/$userid/$postid
adresindeki gönderilerinde ikinci bir giriş oluşturmak için kullanılabilir.
Bu yolları kullanarak, tek bir update()
çağrısıyla JSON ağacındaki birden fazla konumda eşzamanlı güncellemeler gerçekleştirebilirsiniz, örneğin bu örneğin her iki konumda da yeni gönderiyi nasıl oluşturduğu gibi. Bu şekilde yapılan eşzamanlı güncellemeler atomiktir: ya tüm güncellemeler başarılı olur ya da tüm güncellemeler başarısız olur.
Bir tamamlama geri araması ekleyin
Verilerinizin ne zaman işlendiğini bilmek istiyorsanız, tamamlama geri aramalarını kaydedebilirsiniz. Hem set()
hem de update()
, yazma veritabanına işlendiğinde ve arama başarısız olduğunda çağrılan başarı ve hata geri aramalarını iliştirebileceğiniz Future
s'yi döndürür.
FirebaseDatabase.instance
.ref('users/$userId/email')
.set(emailAddress)
.then((_) {
// Data saved successfully!
})
.catchError((error) {
// The write failed...
});
Verileri sil
Verileri silmenin en basit yolu, o verinin konumuna referansla remove()
işlevini çağırmaktır.
set()
veya update()
gibi başka bir yazma işlemi için değer olarak null belirterek de silebilirsiniz. Tek bir API çağrısında birden çok alt öğeyi silmek için bu tekniği update()
ile kullanabilirsiniz.
Verileri işlem olarak kaydet
Artımlı sayaçlar gibi eşzamanlı değişikliklerle bozulabilecek verilerle çalışırken, bir işlem işleyicisini runTransaction()
işlevine geçirerek bir işlem kullanabilirsiniz. Bir işlem işleyici, verilerin mevcut durumunu argüman olarak alır ve yazmak istediğiniz yeni istenen durumu döndürür. Yeni değeriniz başarıyla yazılmadan önce başka bir istemci konuma yazarsa, güncelleme işleviniz yeni geçerli değerle tekrar çağrılır ve yazma yeniden denenir.
Örneğin, örnek sosyal blog uygulamasında, kullanıcıların gönderilere yıldız eklemesine ve yıldızları kaldırmasına izin verebilir ve aşağıdaki gibi bir gönderinin kaç yıldız aldığını takip edebilirsiniz:
void toggleStar(String uid) async {
DatabaseReference postRef =
FirebaseDatabase.instance.ref("posts/foo-bar-123");
TransactionResult result = await postRef.runTransaction((Object? post) {
// Ensure a post at the ref exists.
if (post == null) {
return Transaction.abort();
}
Map<String, dynamic> _post = Map<String, dynamic>.from(post as Map);
if (_post["stars"] is Map && _post["stars"][uid] != null) {
_post["starCount"] = (_post["starCount"] ?? 1) - 1;
_post["stars"][uid] = null;
} else {
_post["starCount"] = (_post["starCount"] ?? 0) + 1;
if (!_post.containsKey("stars")) {
_post["stars"] = {};
}
_post["stars"][uid] = true;
}
// Return the new data.
return Transaction.success(_post);
});
}
Varsayılan olarak, işlem güncelleme işlevi her çalıştırıldığında olaylar oluşturulur, bu nedenle işlevi birden çok kez çalıştırırsanız, ara durumları görebilirsiniz. Bu ara durumları bastırmak için applyLocally
false
olarak ayarlayabilir ve bunun yerine olaylar ortaya çıkmadan önce işlemin tamamlanmasını bekleyebilirsiniz:
await ref.runTransaction((Object? post) {
// ...
}, applyLocally: false);
Bir işlemin sonucu, işlemin yapılıp yapılmadığı ve yeni anlık görüntü gibi bilgileri içeren bir TransactionResult
olur:
DatabaseReference ref = FirebaseDatabase.instance.ref("posts/123");
TransactionResult result = await ref.runTransaction((Object? post) {
// ...
});
print('Committed? ${result.committed}'); // true / false
print('Snapshot? ${result.snapshot}'); // DataSnapshot
Bir işlemi iptal etme
Bir işlemi güvenli bir şekilde iptal etmek istiyorsanız, bir AbortTransactionException
oluşturmak için Transaction.abort()
öğesini çağırın:
TransactionResult result = await ref.runTransaction((Object? user) {
if (user !== null) {
return Transaction.abort();
}
// ...
});
print(result.committed); // false
Atomik sunucu tarafı artışları
Yukarıdaki kullanım durumunda, veritabanına iki değer yazıyoruz: gönderiye yıldız koyan/yıldızı kaldıran kullanıcının kimliği ve artan yıldız sayısı. Bu kullanıcının gönderiyi paylaştığını zaten biliyorsak, işlem yerine atomik bir artış işlemi kullanabiliriz.
void addStar(uid, key) async {
Map<String, Object?> updates = {};
updates["posts/$key/stars/$uid"] = true;
updates["posts/$key/starCount"] = ServerValue.increment(1);
updates["user-posts/$key/stars/$uid"] = true;
updates["user-posts/$key/starCount"] = ServerValue.increment(1);
return FirebaseDatabase.instance.ref().update(updates);
}
Bu kod bir işlem işlemi kullanmaz, bu nedenle çakışan bir güncelleme varsa otomatik olarak yeniden çalıştırılmaz. Ancak artırma işlemi doğrudan veritabanı sunucusunda gerçekleştiği için çakışma ihtimali yoktur.
Bir kullanıcının daha önce yıldız verdiği bir gönderiye yıldız eklemesi gibi uygulamaya özgü çakışmaları algılamak ve reddetmek istiyorsanız, bu kullanım durumu için özel güvenlik kuralları yazmalısınız.
Verilerle çevrimdışı çalışın
Bir istemci ağ bağlantısını kaybederse uygulamanız düzgün çalışmaya devam eder.
Bir Firebase veritabanına bağlı her istemci, tüm etkin verilerin kendi dahili sürümünü korur. Veri yazıldığında, önce bu yerel sürüme yazılır. Firebase istemcisi daha sonra bu verileri uzak veritabanı sunucularıyla ve diğer istemcilerle "en iyi çaba" esasına göre senkronize eder.
Sonuç olarak, veritabanına yapılan tüm yazma işlemleri, herhangi bir veri sunucuya yazılmadan hemen önce yerel olayları tetikler. Bu, uygulamanızın ağ gecikmesinden veya bağlantıdan bağımsız olarak yanıt vermeye devam ettiği anlamına gelir.
Bağlantı yeniden sağlandıktan sonra uygulamanız, herhangi bir özel kod yazmak zorunda kalmadan istemcinin geçerli sunucu durumuyla eşitlenmesi için uygun olay kümesini alır.
Çevrimiçi ve çevrimdışı yetenekler hakkında daha fazla bilgi edinin bölümünde çevrimdışı davranış hakkında daha fazla konuşacağız.