State Management & MobX İle Yukarılara Uçuş — Part 3

State Management Nedir ? MobX Nasıl Kullanılır ?

Samet Çilingir
Flutter Students Club

--

Herkese merhabalar! Ben Samet. Umarım gününüz güzel geçiyordur.

Bu yazı serisinde size bir projeye başlarken çok temelden ihtiyacınız olacak kolay ve efektif bir mimari yapıyı ve bu yapıyla beraber durum yönetiminin nasıl yapabileceğini göstereceğim.

Sırasıyla problemi analiz edip, bu problem doğrultusunda ihitiyaçlarımıza yönelik çözümleri kavrayıp bu çözümlerin koda dökülmesine kadar olan adımları beraber izleyeceğiz.

4 tane alt makale olarak izleyeceğimiz bu seride akla gelebilecek birçok soruyu yanıtlamaya çalışacağım. O zaman haydi başlayalım.

Alt Başlıklar

  • Part 1 — Design Pattern Nedir ? MVVM Nasıl Kullanılır ?
  • Part 2 — Dependency Injection Nedir ? GetIt Nasıl Kullanılır ?
  • Part 3 — State Management Nedir ? MobX Nasıl Kullanılır ?
  • Part 4 — Gelin Bir Örnek Yapalım.

İçerik

  • Problem Tanımı
  • State Management Kavramı
  • MobX Kütüphanesi
  • Kaynakça
  • Kapanış

Problem Tanımı

Flutter’da ekranımızda gösterdiğimiz birçok widget vardır. Bu widgetlar stateless (statik) ve stateful (dinamik) olarak ayrılıyorlar. Arayüzde her widgetı stateful olarak tanımlamak ekran ile her etkileşimde tüm ekranı yenileyeceği için mantıklı değildir. Bu dengeyi yakalamak ve sadece gereken widgetı dinamik yapmak için state management kütüphanesi kullanmamız gerekiyor.

Ayrıca bu problemlere karşılık gelen çözümler birbirinden farklı olabilir veya hiçbir kütüphane kullanılmadan da üstesinden gelinebilir.

State Management Kavramı

State Management (Durum Yönetimi), meydana gelen durumları arayüze bildirmesi için kullandığımız yapıdır.

Flutter kendi içinde setState metoduna sahiptir. Bu metod çalıştırıldığında sadece kendi içine yazılan fonksiyona bağlı değişiklikleri meydana getirir. Sadece StatefulWidget ile kullanılan bu metod, arayüzün tamamını yeniden çizerek değişiklik olan kısmı ile beraber önümüze getirir. Anlaşılacağı üzere bu tavsiye edilen bir yöntem değildir.

State management ile programın akışını tüm bileşenleri arasında senkronize etmemizi sağlayan bir tasarım modelini kullanmış oluruz. Bu sayede sadece ekrandaki sayfayı değil, başka bir sayfadaki değeri de değiştirebiliriz.

MobX Kütüphanesi

MobX, uygulamanızın reaktif verilerini kullanıcı arayüzüne (veya herhangi bir gözlemciye) bağlamayı kolaylaştıran, içinde gözlemlenebilir ve tepki gösteren verileri sağlayan bir tasarım deseninin uygulamasıdır. Reaksiyonlar tetiklenerek gözlenebilir veriler değiştiğinde, gözlemlenen arayüz kısımları yeniden çizilmeye başlar. 3 ana bileşeni 1 tane widget bileşeni vardır. Bunların dışında reaktifler adında özel birimleri de vardır.

Kullanıcıdan gelen reaksiyon, aksiyonu tetikler bu da gözlemlenebilir verileri değiştirir ve geri reaksiyon olarak arayüze haber gönderir. 3 temel bileşeni vardır. Bu bileşenler mobx in sağladığı store sınıfı içine yazılarak kullanılır.

MobX Stores: Bu sınıf gözlemlenebilir verileri ve aksiyon veren metodları tutar. .g.dart dosyasını oluşturarak daha hızlı ve kolay kod yazmayı sağlar.

import 'package:mobx/mobx.dart’;
part 'mobx_store.g.dart’;
class MobxStore = _MobxStoreBase with _$MobxStore; abstract class _MobxStoreBase with Store {

}

Observables: Değerini gözlemleyeceğimiz değişkenler için kullanılan yapılar.

@observable 
int value = 0;

Computed Observables : Türetilmiş duruma bağlı olarak hesaplanan yapılar.

@computed
bool get isValueEven => value.isEven;

Actions: Gözlemlenebilirleri değiştirdiğimiz metodlar.

@action
void increment() {
value++;
}

Bu işaretlemeleri ekledikten sonra build runner’ı çalıştırmak gerekmektedir. Build runner bize otomatik olarak g.dart dosyası oluşturacaktır. Bu dosya etiketlenen değerlerin uzun kodlarının yazılmış halidir. Aşağıdaki kodları terminale yazarak build runner’ın izleme özelliği çalıştırılır. Terminali kapattığınızda otomatik olarak duracaktır. (VS code eklentisi ile kısa yoldan çalıştırabilirsiniz.)

flutter pub run build_runner watch //İlk çalıştırma içinflutter pub run build_runner watch --delete-conflicting-outputs //Hata alıyorsanız

Ayrıca gözlemlenebilir değerlerin arayüz içinde hangi widget’ta olduğunu göstermek gereklidir.

Observer Widget: Gözlemlenebilir değer içeren widgetları sarmalamak için kullandığımız widget.

Observer(builder: (_) {
return Text('${counter.value}',);
})

Reaksiyonlar: Gözlemlenebilirler değiştiğinde, StatefulWidget içinde tetiklenen yapılardır. 4 farklı çeşiti vardır. İşleri bittikten sonra dispose edilmesi gereklidir. Ayrıca initState metodunda kullanılarak kendiliğinden tepki vermesi sağlanabilir.

  • ReactionDisposer autorun(Function(Reaction) fn):

fn içindeki gözlemlenebilirlerdeki herhangi bir değişikliğe bağlı olarak çalışır.

String greeting = Observable('Merhabalar');

final dispose = autorun((_){
print(greeting.value);
});

greeting.value = 'Merhaba MobX';

//autorun bittiği zaman
dispose();
// Çıktılar:
// Merhabalar
// Merhaba MobX
  • ReactionDisposer reaction<T>(T Function(Reaction) fn, void Function(T) effect):

fn içinde kullanılan gözlemlenebilirleri izler ve izleme işlevi farklı bir değeri döndürdüğünde effect’i çalıştırır. Yalnızca fn içindeki gözlemlenebilirler izlenir.

String greeting = Observable('Merhabalar');

final dispose = reaction((_) => greeting.value, (msg) => print(msg));

greeting.value = 'Merhaba MobX'; // Değer değişiyor

//reaction bittiği zaman
dispose();


// Çıktılar:
// Merhaba MobX
  • ReactionDisposer when<T>(bool Function(Reaction) predicate, void Function() effect):

predicate içinde kullanılan gözlemlenebilirleri izler ve true döndüğünde effect’i çalıştırır. effect çalıştırıldıktan sonra, otomatik olarak kendini yok eder. Tek seferlik bir tepki olarak düşünülebilir. Ayrıca when önceden kendini dispose eder.

String greeting = Observable('Merhabalar');

final dispose = when((_) => greeting.value == 'Merhaba MobX', () => print('Biri MobX i selamladı'));

greeting.value = 'Merhaba MobX'; // Değer değişiyor, effect ve disposes çalışıyor


// Çıktılar:
// Biri MobX i selamladı
  • Future<void> asyncWhen(bool Function(Reaction) predicate):

asyncWhen, when’e benzer. Ayrıca predicate’in true döndürmesini bekleyen bir Future yapısı vardır.

final completed = Observable(false);

void waitForCompletion() async {
await asyncWhen(() => completed.value == true);

print('Tamamlandı');
}

Kapanış

Yazının sonuna kadar geldiğimiz için çok teşekkürler. Umarım keyif almışsınızdır. Aşağıdaki kanallardan beni takip etmeyi ve destek olmayı unutmayın.

Twitter: https://twitter.com/sametcilingirrr

Linkedin: https://www.linkedin.com/in/sametcilingir/

Ve ayrıca…

When you help someone, you help everyone.

--

--