Flutter State Management Approaches
Bu blog yazısında flutter durum yönetimi ve yaklaşımlarını değerlendireceğim.
Öncelikle kullanacağımız terimleri inceleyelim.
Durum : Bir şeyin içinde bulunduğu koşulların hepsi, vaziyet, hâl, keyfiyet, mevki, pozisyon
Yönetim : Yönetme işi, çekip çevirme, idare
Flutter’da durum yönetimi karmaşık bir konudur. Sadece sayfa özelinde durumları kontrol etmek bir noktada yeterli gelmeyecek ve tüm uygulamada durumu yönetmek zorunda kalacaksınız.
Yukarıda formül uygulamanın durumu değiştiğinde kullanıcı ara yüzünün yeniden çizildiğini göstermektedir. Flutter bu çizimleri declarative UI (bildirime dayalı kullanıcı arabirimi) yaklaşımı ile oluşturur.
Declarative UI olmayan yaklaşımda ViewB oluştuğunda b nesnesini değiştirerek (mutating) ikinci görseldeki görünümü elde edebiliyor.
// Imperative style
b.setColor(red);
b.clearChildren();
ViewC c3 = new ViewC(...);
b.add(c3);
Declarative UI yaklaşımında ViewB nesnesi tekrar oluşturur. En yaygın olarak Stateful üzerinden setState çağrılarak yapılır.
Not: Durum değişikliğinden etkilenmeyen widgetlar için const kullanılmasının avantajı olacaktık çünkü bu widgetlar tekrar yaratılmayacağı için çizimi hızlandıracaktır.
// Declarative style
return ViewB(
color: red,
child: const ViewC(),
);
Flutter kendi sitesindeki dokümanda durumları ikiye ayırmış geçici durum (bazen UI durumu veya yerel durum olarak adlandırılır) ve uygulama durumu (Local state(sometimes called UI state or local state) and App state).
Geçici Durum (Ephemeral state)
Tek bir widgettin içereceği durum.
Geçici Olmayan Durum (App State)
Uygulamanızın birçok bölümünde paylaşmak ve kullanıcı oturumları arasında tutmak istediğiniz durumu uygulama durumu olarak adlandırırız (bazen paylaşılan durum olarak da adlandırılır).
There is no clear-cut rule (Kesin bir kural yok)
Uygulamanızdaki tüm durumu yönetmek için State ve setState()’i kullanabilirsiniz. Aslında, Flutter ekibi bunu birçok basit uygulama örneğinde yapıyor (her flutter oluşturmada aldığınız başlangıç uygulaması dahil).
Belirli bir değişkenin geçici mi yoksa uygulama durumu mu olduğunu ayırt etmek için net, evrensel bir kural yoktur. Bazen, birini diğerine yeniden düzenlemeniz gerekir.
BottomNavigationBar widget’ini ele alalım. Parametre olarak seçili sekmenin pozisyonunu ve onTap fonksiyonu istiyor.
Stateful içerisinde _currentIndex tanımlayıp bunu BottomNavigationBar içerisinde kullanıp onTap fonksiyonunda seçilen pozisyonu _currentIndex’e atayıp setState yaparsak bu durumda local state yapmış oluyoruz.
Widget ağacındaki görüntü yukarıdaki gibi olduğunu düşünelim.
Peki ikinci sayfadaki butona bastığımızda bottom barın birinci sayfaya geçmesini gerekiyorsa ne olacak. Widget ağacında altta olduğumuz için _currentIndex parametresine erişemeyeceğiz. İşte bu durum AppState oluyor.
Şimdiye kadar durum yönetiminin ne olduğunu aktarmaya çalıştım. Yazının devamında bu durum yönetimi yaklaşımlarına göz atacağız.
https://docs.flutter.dev/development/data-and-backend/state-mgmt/options
Flutter’ın kendi sitesinde bile birçok durum yönetimi yaklaşımlarından (state manager approaches) bahsettiğini görmüşsünüzdür. Eee bunların farkı ne o zaman dediğinizi duyar gibiyim. Çok basit bunlar durum yönetimi yaklaşımıdır.
Yaklaşım : Bir konuyu, sorunu ele alış, inceleyiş, ona bütünsel olarak bakış biçimi.
Bu yöntemleri iki gruba ayırabiliriz. Stateful (setState) kullananlar ve InheritedWidget kullananlar olarak.
Stateful: Bloc, Riverpod , setState, Redux, MobX, Binder, GetX, states_rebuilder, Triple Pattern, solidart, flutter_reactive_widget
InheritedWidget: Provider, InheritedWidget & InheritedModel
Projenize en uygun olan durum yönetimi yaklaşımını seçmek için avantajları ve dezavantajları proje özelinde değerlendirmeniz gerekebilir. Bu paketlerin her biri, yazılımcıların ihtiyaçlarını karşılamak ve sorunlarını çözmek için geliştirilmiştir.
Özet:
Durum yönetim yaklaşımlarını ihtiyacımıza göre seçmeliyiz.
Declarative UI yaklaşımından dolayı hangi durum yönetimi yaklaşımını kullandığınız fark etmeksizin widgetların gereksiz yere yeniden çizilmesini engellemeliyiz.
Yazıyı sonlandırmadan önce kendi tercih ettiğim yöntemden de bahsetmek isterim. Genellikle projelerimi MVVM üzerine kurguluyorum. ViewModel arkasınada Repository ekleyerek temiz bir mimari oluşturuyorum. Bu mimarideki bağımlılıkları yönetmek içinde Get_it paketini tercih ediyorum. Injectable paketi get_it paketini daha pratik kullanmamı sağlıyor. Durum yönetimi içinde Stateful widgetin State’inden kalıtım alıp abstract BaseState oluşturuyorum daha sonra get_it ile viewModel’i çağrıp initState’inde ViewModel(ChangeNotifier)’ina addListener ekleyerek state’i güncelliyorum.