Real Time Flutter App -Shoppi Flutter Mobile

Veli Bacık
HardwareAndro
Published in
7 min readApr 12, 2020

Selamlar herkese, uzun bir aranın ardından çok güzel bir içerik ile sizlerleyim. Servis ile ilgili olan yazımıza buradan, web yazımıza ise buradan ulaşabilirsiniz.

Backend
Ürünlerin saklanabilmesi için Mongo DB kullanılacaktır.
- Bir servis yazılarak, buradan ürün listesi ilgili client lara açılacaktır.
- Real time servis için Socket IO kullanılacak ve buradan ürün güncelleme işlemleri anlık olarak yapılıp yine ilgili web/mobile client lara sunulacaktır.

Mobile
Cuberto tarafından hazırlanmış tasarımın flutter ile çizilmesi gerekiyor.
- Ekran çizimlerinin ardından arka hizmet(backend service) olarak adlandırdığımız yapının bağlanmalıdır.
- Son olarak anlık olarak(real time) herhangi bir ürünün fiyatı veya adeti değiştiğinde mobil alıcı(client) uyarmalıdır.

Front
Admin paneli olarak düşünülmeli ve backend service den bilgiler ürünler çekilmelidir.
- Ürün ekleme ve ürün güncelleme işlemleri yapılmalıdır.
- Herhangi bir ürün değişikliği ilgili client lara real time olarak haber verilmelidir.

Bu yazıda mobil kısımı inceleyeceğiz. Back end yazısına buradan, front end admin paneline ise buradan ulaşabilirsiniz.

https://dribbble.com/shots/6120171-Groceries-Shopping-App-Interaction

Biraz düşünelim, ilk gördüğümüzde neler yapabilirdik, nelere ihtiyacımız var, belirleyelim.

İyi analiz, iyi bir bina yapımının en önemli noktasıdır. Binayı daha hızlı üretmek için sürekli yeni bir eleman almak yerine, ihtiyaçlarınızı ve isteklerinizi belirlerseniz çok daha hızlı ve kaliteli bir bina yapabiliriz.

Sayfaların analizine gelelim.

  • Yukarıdaki içeriği tasarımı incelediğimizde gözümüze ilk çarpan sayfa şeması: Ürün Sayfası — Ürün Detay ve Ürün Satın alma olarak üç sayfamız mevcut.
  • Ürün sayfası ve ürünün satın alma sayfasının tasarımda dikkat edilmesi ve orada ki el haraketi ile kaydırmanın nasıl yapılabileceği düşünmek gerekiyor.
  • Detay sayfasına geçerken, hangi ürüne dokunulursa o ürün yan sayfaya animasyonlu geçmekte ve eğer yan sayfadan bir ürün eklenirse sepete ürün sayfasında alt taraftan bir menu açılmakta.
  • Menü içerisinde gelen ürünlerin bir iki üç gibi değerleri alması ve sağa doğru kaydırılması gerekmektedir.
  • Kullanıcın el kaydırması ile ürün ekranı EKRAN olarak değişmeli ve yukarı aşağı çekilerek ekranlar arasında geçilmelidir.
  • Ürün satın alma sayfasında, ürün detaydan eklenenler ile ortada gösterilmeli ve eklenen ürünlerin fiyatının belirli bir limiti geçmesi ile alttaki teslimat barı dolmalıdır.

Buraya kadar yaptığımız, hiçbir yazılım dili olmaksızın bir mobil ekranın tasarımını yaparken düşünmemiz gereken en önemli noktalardır.

Time to Flutter

Gerçek hayatı düşünecek olursak yani bir şirket için bir kurum için uygulama geliştiriyor olsaydık; yukarıdaki yaptığımız analizi bize ya bir P.M(project manager) ya P.O(Product Owner) yada Analiz yapan arkadaşımız anlatacaktı ve biz uygulamayı tasarlamaya başlayacaktık.

Teknik Tasarım

  • 3 Ekran var olduğunu gördük ve incelediğimizde aslında iki tip widget kullanmamız gerektiği ortaya çıkıyor.
    - Ürün sayfası ve ürün satın alma sayfasının el hareketi ile geçmesi önemli bunu ya “ListView” yada “PageView” yapmalıyız. Farkı ise şu ListView daha çok ürün listesi gibi yerlerde kullanılırken PageView bütün ekranı kaydırıp geliştirmek için yapılır.
  • Ürün ekranından yan ekrana geçerken ilgili ürünün detay bilgisi “Navigation” ile taşıyoruz ve sayfaya geçerken ilgili geçiş animasyonları için “Hero” kullanıyoruz.
  • Ürün detaydan herhangi bir ekleme işlemi yapıldığında ürün sayfasındaki durumu(state) değiştirmek gerekiyor bunu en kolay ve en hızlı yöntem olan “Provider” State Management yöntemini kullanıyoruz.
  • Tüm sayfaları tasarlarken “Panache Theme” ile bir tema üretiyoruz ve bu tema üzerinden tüm ekranın stilleri tanımlıyoruz.
  • Ekranlarımızdaki tüm çizimlerimizin widget olduğunu asla unutmadan her şeyi “Atomic” olarak olabildiğince küçük bir şekilde tasarlayıp ekranlarımıza ekliyoruz.

We’re not designing pages, we’re designing systems of components. — Stephen Hay

Klasör Yapımız

  • En severek kullandığım ve gayet temiz olarak düşündüğüm feature base olarak adlandırılan yapı ile kuruyorum.
    - Core altındaki olanlar projenin üstünde sistemsel olarak kullandığım özellikleri içeriyor
    - Features altı ise projenin kendi bileşenlerinin ve sayfaların çizildiği ana alan olarak gösterebilirim.

Başlangıç noktamız: main.dart

  • Projenin üç ekranının öncelikle bir temelden türemesi gerekmektedir.
  • Detay sayfasından gelen ürünlerimizi taşımak için projemizi provider ile sarmalamak gerekiyor.
  • Projenin temasını ise ana dosyamızda vermemiz gerekiyor.

Sıra şimdi ana sayfamızda : shop_view.dart

  • Ürün ve ürün satın alma sayfalarını kapsaması gerekiyor yani bunların bir PageView ile sarmalanması gerekir.
  • Bu sayfada güzel özelliklerden biri PageView “controller” özelliğinin tatlı bir yanı olmasıdır. Sayfalardan geçişlerde sağdan ve soldan 20 boşluk verilip bir sonraki gelen kartın önüzlenmesi istenir.
    - Bu noktada PageView çalışma mantığı olarak tüm sayfayı geçiş sağlar ama biz boşluk vermek istiyor isek viewportFraction belirlememiz gerekiyor.
  • “OnPage changed” ise sayfa değiştiğinde alt bar’ın gözükmesi veya kapanması için kullanıyorum.

Peki anasayfamız hazır gelelim ürün sayfamıza: shop_list_view.dart

  • Bu ürünlerimiz iki kolonlu gözüküyor bu yüzden GridView kullanmamız gerekiyor.
  • Sayfa ilk girildiğinde bir istek atması gerekiyor bu konuda en güzel kullanım “FutureBuilder” size attığınız isteğin her sonucunu döndürmekte
    - Gelen istekte gelen cevap dolu mu?, boş mu?, hata var mı?, yada giden istekte internet isteğinde bir sorun oldumu bunların hepsini kontrol edebiliriz.

Çok önemli ve basit bir nokta var biz eğer ana bir FutureBuilder tanımlar isek tüm isteklerimizin sonuçlarında gelen senaryoları tek bir yerde çözmüş ve tekrar tekrar uğraşmamız olacağız.

  • Ekranımızı tasarlar iken sürekli bize lazım olacak özelliklerimiz var. Misal anlık tema değeri veya o anki yükselik değeri bunları her defa çağırmak yerine “BaseState” yazarak bunu tekrar bunları yazmaktan kurtulmuş oluruz.
  • Buradaki yine önemli bir noktada sayfa içerisindeki kaydırma yaparken üst kısmındaki barın animasyonlu haraketleri yapmasıdır. Bunun için Sliver list kullanıyoruz ve çok esnek bir ekran elde etmiş oluyoruz.
  • Hero taglarımız sayfalardan geçiş yaparken yapılacak animasyonlar ile ilgili olarak verilir. Önemili olan ana sayfa ile detay sayfasında geçerken aynı etiketli elemanın olması çünkü hero widget etiket değerine göre çalışıyor.
  • Ekrandaki bir önemli nokta ise alt bardaki elemanların detaydan gelecektir. Bu elemanların state değeri başka yerleden değişebileceği için bunu çok basit bir şekilde Consumer olarak tanımlıyoruz yani en başta verdiğimiz değeri dinleyecek ve değişikliklere göre ekran kendini çizecek.
  • Son olarak sayfada “AnimatedContainer” kavramına dikkat etmeniz gerekir. Çok basit olarak herhangi bir yükseklik değişikliğinde kendini animasyonlu bir şekilde yükseltip azaltıyor.
  • Burada bir önemli noktada sayfamızın temaları, hepsi ana teme dosyasından gelmektedir ve bu sayede kontrollü bir şekilde geliştirme yapabilmekteyiz.

Sıra şimdi ana sayfamızın detayında : shop_view_detail.dart

  • Bu sayfada tasarımız basit bir liste tasarımı olmakta sadece Hero ile vereceğimiz widgetin etiketlerinin aynı olması önemlidir.
  • Bu etiketin anasayfamızda ürüne dokunduğumda yana doğru açarken taşıdığımız ürünün detay key’i olduğunu unutmayın.
  • Bu sayfamızda en önemli nokta ürünümüzü sepete eklerken önceki sayfadaki bir listeye ekleme olacağı için State Management için kurguladığımız yapıyı kullanarak elemanımızı oraya ekleyip veya düzenleyip göndereceğiz.

Provider.of<ProductListNotifier>(context, listen: false).addProduct(data);

Ürün işlemlerini bitirdiğimize göre sıra: shop_payment_view.dart

  • Sayfamız da önemli olan nokta bir scroll işlemi olmaksızın tek bir sayfaya bu ekranın sığabilmesi için “Column” kullanmamız gerekiyor.
  • Bir diğer önemli nokta Spacer elamanının varlığıdır. Bu eleman çok küçük gözüksede “responsive design” yapabilmek adına çok önemlidir.
    - Spacer dediğimizde flex:1 olan bir view üretmiş oluyoruz.
    - Tüm sayfamızı düşünelim eğer o ekranda birden fazla eleman var ve bunlar Expanded ve Spacerler ile verilmiş ise sayfa aslında parça parça bölünmüş ve yükseklik genişlik olmaksızın kendinini otomatik konumlandırabilmektedir.
  • Burada ekranı tasarlar iken çok basit tutmayı ve atomik olarak parçalamayı esas alarak yapmış bulunuyoruz.
  • Ve burada ürün listesi bizim provider ile sakladığımız state içinden geliyor ve güncelleniyor.

Sayfalarımızın tasarımını tamamladık sıra servis işlemlerimizde

  • Ürün listesini çektiğimiz servis hazırlamalıyız ve bu adımda bir ağ istekleri yönetmek için paket kullanmamız gerekiyor.(Zorunlu değil ama bu işler için yazılmış ve tüm isteklerinizi yönetebileceğiniz iki paket mevcut. Birisi http diğeri ise dio).
  • Bu projede dio ile ilerledik ve ilerlerken tüm configlerimizin belirli bir yerden yönetilmesi için bazı ayarlar yapmamız gerekiyor.
  • Bu projede dinamik olarak sadece get servisini dinamik olarak hazırladık diğer yazılarda tüm paketleri entegre etmiş olacağız.
  • Burada tüm modelleriimizde ortak olması için toJson ve fromJson olan bir abstract class tanımlayıp tüm response modellerimizin oradan dönmesini zorunlu tutuyoruz.
  • Burada yine önemli nokta ise kendi yazdığımız make metodu ile requestlerimizi yönetiyoruz ve gelen response göre kendi logiclerimizi yazıyoruz.
  • Config dosyamızda ise şuanlık sadece bir plattform için düşünüp base url’leri platforma göre veriyorum. Devamında basit olarak TimeOut değeride vererek servislerimizin isteklerini yönetmiş oluyoruz.

Servis kısmımız tüm projlerde dinamik olarak kullanılacak şekilde hazırlandı. Peki Real Time olarak dinlemeyi yapıp değişiklikleri nasıl yapacağız?

Tam burada sıra : shop_view_model.dart

  • Burada oluşturduğumuz sınıfın “Change Notifier” dan türemiş olması bize şu gücü kazandırıyor: Onu dinleyen o sınıftan değer alan herkesi uyarma ve yenileme şansına sahip oluyoruz.
  • Bu sınıf ilk olarak sayfa ile bağlantı kurduğu anda socket ile bağlantı kurup socket’ten gelen mesajları dinlemektedir.
  • Socketten gelen mesajlar backend tarafından bize index,model olarak dönmekte ve bu gelen modelı bizim listemizdeki var olanla güncelleyip ekranımızı tekrar çizdiriyoruz.

Servis’lerimiz ekranlarımız tamam peki tam projemiz bitti derken atomic olarak neler yaptık birde ona bakalım

Sıra atomic component’lerimizde: Core/View/Widget

  • Bu projede kullanırken çok fazla sayfa olmadığı için parçalamak için devasa uğraşmadım ama şu haliyle dahi diğer bir çok projemde kullanabileceğim , proje bağımsız widgetler üretmiş oldum.

Birini inceleyecek olur isek: number_circle_avatar.dart

  • Ürünlerimizin üstünde kırmızı bir iki üç olarak çıkacan badge olarak da bildiğimiz bir widget ürettik.
  • Burada kendi karaımıza göre eğer değer gelmez ise 0 değerini verip herhangi bir badge de değer göstermedik.
  • Bir diğer önemli konu hiçbir değeri elle vermediğimiz için her app’in kendi temasına göre renk ve şekil alacaktır.

Ve mobil uygulamamız hazır 🎊🎊

Mobil projemizin kaynak kodlarına buradan erişebilirsiniz.

Flutter ile ilgili daha çok bilgi merak ediyorsanız, kanalımıza beklerim.

Sevgilerimle
Emeğin kutsallığına inanan herkese selam olsun!

--

--

Veli Bacık
HardwareAndro

We always change the world, so just want it. [OLD]Google Developer Expert Flutter & Dart, Gamer, Work More!