Flutter’a Firebase Entegrasyonu ve Temel İşlemler 2: Firestore

Barış Kodaş
Flutter Students Club
8 min readJan 12, 2022

Merhaba,

Bu makale serisinde Firebase servislerinden bahsediyoruz ve serinin ikinci konuğu Cloud Firestore servisi.

Firestore nedir, neden kullanılıyor?

Firestore, karmaşık ve büyük verileri bulutta tutmamıza yarayan; gelişmiş sorgulamalar ve kurallandırmalar yapabildiğimiz, Google tarafından geliştirilen gerçek zamanlı bir NoSQL veritabınıdır. Uygulamamızdaki kullanıcı verileri ve diğer verileri depolamak için kullanıyoruz.

NoSQL nedir?

‘NoSQL’ terimi, ilişkisel olmayan veritabanı türlerini ifade eder ve bu veritabanları, verileri ilişkisel tablolardan farklı bir formatta depolar. SQL veritabanlarına göre çok daha hızlı ve esnek bir yapıdadır. Bu konuyu biraz daha açacak olursak; diyelim ki SQL veritabanı ile çalışıyorsunuz ve bir kullanıcılar tablonuz var. Bu tabloda kullanıcının ad-soyad, mail ve telefon verilerini tutacak şekilde tasarladınız, aradan biraz süre geçti ve adres bilgilerini tutacak bir alana daha ihtiyacınız oldu. SQL veritabanında bu işlemi yapmak için diğer tabloları ve veritabanı kurallarınızı yeniden yapılandırmanız gerekebilir ve uzun sürebilir çünkü bütün kayıtlara adres alanı eklemeniz gerekir. NoSQL’de ise böyle bir durum yaşamazsınız, kayıtlar için istediğiniz alanları hızlıca oluşturabilir veya silebilirsiniz, keskin kurallar yoktur; bundan dolayı esnek diyoruz.

NoSQL Veritabanı örneği

Firestore dosya yapısı ve çalışma mantığı

Firestore’da veriler arasında key-value(anahtar-değer) ilişkisi vardır, json dosya formatıyla aynı mantıkta çalışır.

Koleksiyon ve doküman kavramları

from firebase.google.com

Bu konuyu tanım yapmadan sade ve basit bir biçimde doğrudan örnek üzerinden açıklayalım; Örneğin bir telefon bakmak için alışveriş sitesine girdiniz diyelim, Cep Telefonu kategorisine girdiğinizde karşınıza markalar kategorisi çıkar ve herhangi bir markaya girdiğinizde ise o markanın telefon modellerini görürsünüz. Burada başlangıçta “Cep Telefonu” kategorisi bir koleksiyondur ve içinde telefon markalarını tutar, her bir marka ise bir dokümandır. Yani aynı tipte verileri bir arada tutan nesneye Koleksiyon, içindeki her bir veriye ise doküman diyoruz. Bir diğer örneği ise görselden verelim, fiziki bir dosyamız olduğunu düşünelim; bu dosyanın her bir sayfasında da ödevlerimiz var diyelim. Bu durumda şu cümleyi kurabiliriz; bu dosya ödev tipinde veri tutan bir koleksiyondur. Son olarak, bir nesnenin koleksiyon mu yoksa doküman mı olduğunu kendimize şu soruyu sorarak bulabiliriz “bu nesne genel mi, özel mi?”. Eğer “cevap” özel ise o nesne bir dokümandır ve özel verileri tutuyordur, eğer cevap “genel” ise o nesne bir koleksiyondur ve içerisinde özel verileri tutan dokümanları tutuyordur.

Koleksiyon ve Doküman yapısı

Teokrik olarak hazırız, başlayalım! 😎

Öncelikle Firestore veritabanı ile nasıl bağlantı kuruyoruz, okuma-yazma, güncelleme, silme ve sorgu filtreleme işlemlerine bakacağız. Daha sonrasında ise bunları kullanarak ekşi sözlük benzeri bir app geliştireceğiz.

Firestore CRUD işlemleri

Görselden de anlaşılacağı üzere sırasıyla Create (oluşturma, yazma) Read (okuma) Update (güncelleme) ve Delete (silme) metotlatını inceleyeceğiz.

Önce Firestore ile bağlantı kuralım.

Okuma işlemleriyle başlayalım. Burayı kavrarsak gerisi daha rahat anlaşılır.

Yazma işlemleri

Güncelleme

Silme işlemleri

Sorgular

Teorik kısım bu kadardı, artık eğlenceli kısıma geçelim! 🤓

Örnek bir uygulama yazalım.

Bu konu için en iyi örneğin ekşi sözlük benzeri bir app olduğuna karar verdim ve şöyle bir uygulama hazırladım:

Sizin için görselde görüldüğü üzere topluluğumuzun hayali uygulaması olan FSC Sözlük uygulamasını tasarladım.😎 🤙🏻

Bu app’i bir önceki makalemin konusu olan Authentication uygulaması ile birleştirerek üstüne inşa ettim, oturum kontrolü, kayıt ve giriş sistemleri olan, markete atılıp kullanılabilecek bir app diyebiliriz su an icin.

Eğer okumadıysanız bir önceki Authentication makaleme buradan erişebilirsiniz.

Vakit kaybetmeden başlayalım.

cloud_firestore paketini uygulumamıza ekleyelim.

$ flutter pub add cloud_firestore

Bir önceki projemi düzenleyerek başlıyorum, giriş sayfasından sonra bizi sözlük sayfasına yönlendirsin.

ardından main.dart dosyama geliyorum ve onu da düzenliyorum.

daha sonra console.firebase.google.com ‘dan Firestore’u aktif ediyoruz. Test modunda başlayayıp, veri saklamak için eur3 seçeneğini seçmenizi öneririm.

Firestore’da “topics” adında bir koleksiyon oluşturuyorum. Bu koleksiyona oluşturulan konular eklenecek.

Başlamadan önce Firestore’un saklayabildiği veri türlerine bakalım:

Ardından lib/pages/fsc_add_page.dart dosyamı oluşturuyorum ve Scaffold döndüren bir StatelessWidget tanımlıyorum.

(NOT: Bu örnekte Firestore servislerini merkezileştirmeyeceğim, göz alışkanlığı olması ve daha rahat kavranması için böylesinin daha doğru olduğunu düşünüyorum. Servis merkezileştirmeyi bir önceki makalemde anlatmıştım, dilerseniz inceleyebilirsiniz.)

** ve ardından servislerimi import edip AppBar’ın actions parametresine Gönder butonumu ekliyorum. Kullanıcı, bilgilerini girip Gönder’e bastığında topics koleksiyonuna .add() metoduyla bir doküman ekleyeceğiz.

Dipnot: Auth servisiniz aktif değilse; -auth.currentUser!.email- yerine statik bir email tanımlayabilirsiniz. Örn: “user@mail.com” gibi.

Test edelim.

Başarılı bir şekilde çalıştı.

Şimdi Anasayfamızı tasarlayalım ve görselde görüldüğü şekilde veritabanımızdaki konuları listeleyelim. lib/pages/fsc_home.dart dosyamı oluşturup FSCHome adında Scaffold döndüren bir StatefulWidget tanımlıyorum.

Öncelikle UI tasarımıyla başlayalım ve AppBar’ımızı tasarlayalım.

Şimdilik Konu ekleme ve Çıkış butonlarımızı aktif edelim, Sırala butonumuzu daha sonra aktif edeceğiz.

Bu görüntüyü elde ettiysek artık veritabanımızdan konuları çekmeye başlayabiliriz. Öncelikle Firestore arayüzüne bir bakalım;

Arayüzde şunu görüyoruz; topics adında bir koleksiyon var ve içinde otomatik ID ile oluşturulmuş dokümanlar var ve bu dokümanlar belirli bilgiler tutuyor.

Veritabanı yapısını öğrendik, artık verileri çekebiliriz. Bunun için StreamBuilder kullanacağız. Stream kelimesi “akıntı” anlamına gelir ve StreamBuilder widgetı bizden dinlemek için bir Stream ister. Devamlı olarak dinleyip değişiklikleri bize gerçek zamanlı olarak akıtır.

Öncelikle State altına topics koleksiyonunu dinlemesi için StreamBuilder’a vermek üzere bir Stream<QuerySnapshot> tanımlıyorum ve topics koleksiyonumun snapshotını(anlık görüntü) veriyorum.

Bunu QuerySnapshot tipinde tanımlamanız çok önemli, tanımlamadığınız takdirde koleksiyonun bazı verilerine erişemeyebilirsiniz.

ardından Scaffold’un body parametresine geliyorum

Kod
Çıktısı.

topics koleksiyonumuzdaki dokümanları getirdik ve ekrana yazdırdık. Şimdi ise tıklandığında konu sayfasına yönlendirelim. Önce lib/pages/fsc_topic_page.dart içine bir StatefulWidget oluşturuyorum. Daha sonra ise kurucu metoduma önceki sayfadan aktaracağım parametleri tanımlıyorum.

Tekrar konu başlıkları sayfamıza dönelim ve Listile’ın onTap parametresine o anki dokümanın parametlerini vererek konu sayfasına yönlendirelim.

Daha sonra tekrar konu sayfasına dönelim ve gelen verileri ekranda gösterelim.

Alacağımız çıktı şu olacak;

Yeni bir konu açtım, listelendi ve sayfasına gittiğimde bilgileri geldi. Şimdi Düzenle ve Sil butonlarımızı ayarlayalım.

Öncelikle Düzenle butonunu ayarlayalım ve tıklandığında karşımıza bir ModalBottomSheet çıksın. Eğer mevcut kullanıcı ile dokümanı oluşturan kullanıcı aynı kişi ise doküman düzenleme izni verelim, değilse yetkiniz yok diyaloğu gösterelim. Düzenle butonumun onPress parametresine gidiyorum

Kod
Çıktısı

şu an aktif kullanıcı mailimiz deneme@deneme.com ve konuyu oluşturan kişi de bu mail olduğu için güncelle sheeti açıldı, diğer konularda ise “Yetkiniz yok” uyarısı aldık.

Tabi eşleşen durumlar için butonları gösterip eşleşmeyen durumlar için butonları gizleyedebilirdik. Daha iyi bir UI mümkün! 😎

Şimdi de Sil butonumuzu ayarlayalım

Test edelim.

Önce başkasının konusunu silmeye çalıştım yetki uyarısı verdi, daha sonra ise kendi konumu sildim ve başarılı bir şekilde işlem tamamlandı.

Şimdi açılan konulara gelen yanıtları çekelim ve gösterelim.

Yukarıda bahsettiğimiz üzere yanıtları her dokümanın içerisinde oluşturduğumuz “replies” koleksiyonlarında ayrı birer doküman olarak tutuyoruz. Yani burada yapacağımız işlem önce topics koleksiyonuna erişmek sonra konu dokümanına erişmek daha sonra konu dokümanı içerisindeki replies koleksiyonuna erişmek. Burada iç içe ve çok aşamalı koleksiyon-doküman-koleksiyon-doküman ilişkisini kullanmış olduk.

Firestore arayüzünde bakalım:

Görüldüğü üzere her dokümanımızın kendi alt “replies” koleksiyonu ve bu koleksiyon yanıtlarını tutan dokümanları var.

Uygulamamıza dönelim ve her konunun yanıtlarını getirelim, bunun için yine StreamBuilder kullanacağız.

Burada saat-tarihi statik tanımladım çünkü bir cevap yazma ekranı/widgetı tasarlamadım bunu size bırakıyorum. Nasıl yapılacağını artık biliyorsunuz. Bir diğer konu ise Düzenle ve Sil butonlarını da size bıraktım, yukarıda örneklerini yaptık, bunları kendiniz yapabilirsiniz mantık tamamen aynı.

Test edelim.

Yanıtları Flutter Students Club’ın Twitter hesabının paylaşımlarına gelen yorumlardan alıp ben elle ekledim. Size önerim bu sayfanın AppBar kısmına bir add iconu ekleyip cevap yazma penceresi çıkarabilirsiniz, daha sonra veriyi okuduğumuz replies koleksiyonuna bu şekilde yazabilirsiniz. Konu ekleme sayfasındaki işlemin tamamen aynısı!

Ve son bir adım…

Başlangıçta pas geçtiğimiz konu sıralama butonumuzu da kodlayıp projemizi bitirelim. Bunun için yapacağımız şey anasayfadaki Stream<QuerySnapshot> değişkenimizi güncellemek olacak. Bunun için .orderBy() ı kullanacağız.

Test edelim.

Diğer sorgu türlerinden yukarıda bahsetmiştik, onları kullanmayı size bırakıyorum. Örneğin limit sorgusunu kullanarak son eklenen 2 konuyu getir gibi şeyler koyabilirsiniz.

Bu makalede Firestore ile ilgili bilmeniz gereken şeyleri elimden geldiğince anlattım ve anlattıklarımı kapsayan örnek bir uygulama geliştirdim, umarım faydalı olmuştur.

Proje GitHub Linki: https://github.com/bariskodas/FSC_FirestoreExample

--

--