State, Flutter'daki merkezi veri yönetimi nesnesidir, StatefulWidget ile ilişkilidir ve değişebilir bilgileri depolamaktan ve arayüzü oluşturmaktan sorumludur. Resmi Flutter dokümantasyonuna (Flutter.dev, 2026) göre State, widget yaşam döngüsü boyunca var olur ve yeniden yapılandırmalarından sonra da kalarak UI güncellemeleri arasında veri tutarlılığını sağlar. Widget'ın kendisinin aksine State, alanlarını değiştirebilir ve setState çağrısı aracılığıyla yeniden yapılandırmayı tetikleyebilir.
Önemli Noktalar
State, Flutter mimarisinde bir StatefulWidget'ın değişebilir verilerini depolayan ve bu verilerin arayüzde nasıl görüntüleneceğini belirleyen bir nesnedir. Her StatefulWidget, ağaca eklendiğinde createState yöntemi aracılığıyla tam olarak bir State nesnesi oluşturur. State widget'tan bağımsız olarak var olur: ebeveyn StatefulWidget'ı yeni parametrelerle yeniden yapılandırırsa, State aynı kalır ve widget özelliği aracılığıyla güncellenmiş widget'ı alır.
Flutter Mimari Genel Bakış'a (Google, 2026) göre, Widget ve State'in ayrılması, framework'ün ağaç öğelerini yeniden kullanmasına izin veren bilinçli bir mimari karardır. Widget (hafif bir açıklama) birden çok kez oluşturulup yok edilebilir, ancak State (verilerle birlikte ağır bir nesne) öğe ağaçta olduğu sürece bellekte kalır. Bu, ebeveyn widget'ların sık yeniden yapılandırılması sırasında veri kaybını önler.
State, generics aracılığıyla StatefulWidget arayüzünü uygular: class _MyState extends State<MyWidget>. Generic, State'i belirli bir StatefulWidget türüne bağlayarak widget özelliği aracılığıyla alanlarına tür güvenli erişim sağlar.
State nesnesi, StatefulElement içinde depolanır — Widget ve RenderObject arasında bir ara katman. StatefulElement, createState aracılığıyla State oluşturur, ona bir referans tutar ve State'i sahip olarak iletir. Element, yalnızca widget ağaçtan kaldırıldığında yok edilir — o zamana kadar State bellekte yaşar.
State yaşam döngüsü deterministiktir ve katı bir çağrı dizisinden oluşur. Bu diziyi anlamak, doğru kaynak yönetimi ve bellek sızıntılarını önlemenin temelidir.
initState, State oluşturulduğunda ilk olarak çağrılır. Bu yöntemde denetleyiciler, akış abonelikleri, zamanlayıcılar ve alanların başlangıç değerleri başlatılır. İlk satırda super.initState() çağırmak zorunludur. initState aşamasında widget ağacı henüz tam olarak bağlanmamıştır, bu nedenle MediaQuery.of(context) gibi yöntemler doğru çalışmayabilir.
didChangeDependencies, initState'den sonra ve InheritedWidget bağımlılıkları her değiştiğinde çağrılır. MediaQuery.of(context) veya Theme.of(context) initState'de değil, burada çağrılmalıdır çünkü bu noktada ağaç zaten bağlanmıştır. Bu yöntem ayrıca widget, InheritedWidget'ın farklı değerler sağladığı farklı bir bağlama taşınırsa da çağrılır.
build, State'in bir widget ağacı döndüren ana yöntemidir. initState'den sonra, didChangeDependencies'den sonra ve her setState'den sonra çağrılır. build yönteminin yan etkileri olmamalıdır — yalnızca mevcut State alan değerlerine dayalı olarak arayüzü tanımlar.
didUpdateWidget, ebeveyn StatefulWidget'ı yeni parametrelerle yeniden yapılandırdığında çağrılır. State, eski widget'a oldWidget aracılığıyla erişir ve onu yenisiyle karşılaştırabilir. Parametreler değiştiyse, durum güncellenebilir, yeni veriler yüklenebilir veya bir animasyon yeniden başlatılabilir.
dispose, tüm kaynakların (denetleyiciler, abonelikler, zamanlayıcılar) serbest bırakıldığı son yöntemdir. dispose'dan sonra State ölü olarak işaretlenir: mounted false döndürür, setState çağırmak bir istisna fırlatır. Yöntemin son satırında super.dispose() çağırmak zorunludur.
| Yöntem | Ne zaman çağrılır | Zorunlu super |
|---|---|---|
| initState | State oluşturulduğunda | Evet, ilk satırda |
| didChangeDependencies | initState'den sonra ve InheritedWidget değiştiğinde | Evet |
| build | initState, didChangeDependencies, setState'den sonra | Hayır |
| didUpdateWidget | Ebeveynden yeni widget geldiğinde | Evet |
| setState | Geliştirici çağırdığında | Hayır |
| dispose | Ağaçtan kaldırıldığında | Evet, son satırda |
State'in çalışma mekanizması üç temel prensibe dayanır: Element ile ilişkilendirme, setState aracılığıyla reaktivite ve widget özelliği aracılığıyla ebeveyne erişim. Flutter öğe ağacını oluştururken bir StatefulElement ile karşılaştığında, ilişkili widget'ın createState'ini çağırır. Oluşturulan State, öğede depolanır ve öğe kaldırılana kadar var olur.
setState çağrıldığında, State kendini kirli olarak işaretler ve sonraki kare için yeniden yapılandırma planlar. Önemli: setState hemen build'i çağırmaz — yalnızca yeniden yapılandırma ihtiyacını kaydeder. Flutter mevcut karedeki tüm kirli öğeleri toplar ve bunları toplu olarak yeniden yapılandırarak performansı optimize eder. build çağrısından sonra State temiz duruma döner.
widget özelliği, State'in StatefulWidget yapıcısına iletilen parametreleri okumasını sağlar. StatefulWidget değişmez olduğundan (StatelessWidget gibi), alanları değişmez — parametreler değiştiğinde ebeveyn yeni bir widget oluşturur ve State bunu didUpdateWidget aracılığıyla alır. Bu, State'in her zaman güncel ebeveyn verileriyle çalışmasını sağlar.
Bir zamanlayıcı tarafından değiştirilen bir alana sahip temel State örneği. initState, setState ve dispose'u gösterir:
class _TimerWidgetState extends State<TimerWidget> {
int _seconds = 0;
Timer? _timer;
@override
void initState() {
super.initState();
_timer = Timer.periodic(
const Duration(seconds: 1),
(_) => setState(() => _seconds++),
);
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Text('$_seconds seconds elapsed');
}
}
Ebeveyn parametrelerine erişmek ve didUpdateWidget aracılığıyla değişikliklerine tepki vermek için widget özelliğini kullanan örnek:
class _GreetingState extends State<GreetingWidget> {
String _displayName = '';
@override
void initState() {
super.initState();
_displayName = _formatName(widget.name);
}
@override
void didUpdateWidget(GreetingWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.name != oldWidget.name) {
setState(() {
_displayName = _formatName(widget.name);
});
}
}
String _formatName(String name) => name.trim().isEmpty ? 'Guest' : name;
@override
Widget build(BuildContext context) {
return Text('Hello, $_displayName!');
}
}
İkinci örnekte, State giriş parametresindeki (name) değişiklikleri izler ve yalnızca gerçek bir değişiklik olduğunda görüntüyü yeniden biçimlendirir. widget.name != oldWidget.name kontrolü olmadan, yöntem, ad değişmemiş olsa bile her ebeveyn yeniden yapılandırmasında çağrılırdı — framework için gereksiz iş.
State ve StatefulWidget, Flutter mimarisinde farklı roller üstlenen iki farklı sınıftır. StatefulWidget, widget yapılandırmasını tanımlayan ve State oluşturan hafif, değişmez bir sarıcıdır. State, değişebilir verileri depolayan, abonelikleri yöneten ve UI'yi oluşturan ağır bir nesnedir. Bu ayrım, Flutter'ın durumu kaybetmeden widget'ları yok etmesine ve oluşturmasına olanak tanır.
StatefulWidget'ın tüm alanları final olmalı ve yapıcıda ayarlanmalıdır — oluşturulduktan sonra değişmezler. State ise alanlarını istediği zaman değiştirebilir, ancak tüm değişikliklerden önce Flutter'ın yeniden yapılandırma ihtiyacını bilmesi için bir setState çağrısı gelmelidir. Temel fark budur: StatefulWidget “ne gösterileceği”, State ise “nasıl gösterileceği ve hangi verilerin kullanılacağı”dır.
Flutter kaynak kodu analizine (Flutter SDK, 2026) göre, StatefulWidget yalnızca bir zorunlu alan içerir — createState, oysa State'in BuildContext'e erişimi vardır, akışlara abone olabilir, animasyonları ve denetleyicileri yönetebilir. StatefulWidget'ın mümkün olduğunca basit tutulması ve tüm mantığın State'e taşınması önerilir.
Widget ve State'in ayrılması, yapılandırmanın değişmezliğini sağlayan mimari bir karardır. StatefulWidget durumu kendisi depolasaydı, her ebeveyn yeniden yapılandırmasında durum kaybolurdu. Durumu ayrı bir nesneye taşıyarak Flutter, verilerin yeniden yapılandırmalardan sonra kalıcı olmasını sağlarken, widget'lar hafif ve karşılaştırılabilir kalır.
State nesnesi izole edilmiştir — diğer widget'ların State'ine doğrudan erişimi yoktur. Widget'lar arasında veri alışverişi için InheritedWidget veya harici durum yönetim araçları kullanılır: Provider, Riverpod, Bloc, Redux. Her yaklaşım sorunu farklı şekilde çözer: InheritedWidget widget ağacı aracılığıyla, Provider DI kabı aracılığıyla, Bloc olay akışları aracılığıyla çalışır.
Araç seçimi proje ölçeğine bağlıdır. Küçük bir uygulama için InheritedWidget ve yerel State yeterlidir. Orta ve büyük projeler için Riverpod veya Bloc önerilir — test edilebilirlik, öngörülebilirlik ve mantığın UI'dan ayrılmasını sağlarlar. State daha sonra yalnızca yerel widget verileri (odak, kaydırma, animasyon) için kullanılır.
Flutter Topluluk Anketi 2025'e (Flutter Foundation, Aralık 2025) göre Riverpod, yeni projelerde en popüler durum yönetim çözümüdür (%38), onu Bloc (%31) ve Provider (%22) takip etmektedir. Her üç araç da State ile uyumludur ve standart yaşam döngüsünden vazgeçmeyi gerektirmez.
İlk hata, asenkron bir geri çağırmada setState'den önce mounted kontrolünü unutmaktır. Bir widget ağaçtan kaldırıldığında (örneğin, kullanıcı ekrandan ayrıldı), ancak asenkron bir işlem (HTTP isteği) hala devam ediyorsa, tamamlandıktan sonra State zaten ölüdür. Ölü bir State'te setState çağırmak bir istisna fırlatır. if (mounted) setState(...) kontrolü sorunu çözer.
İkinci hata, didChangeDependencies yerine initState'te InheritedWidget bağımlılıklarını başlatmaktır. initState'te bağlam henüz bağlanmamıştır, bu nedenle MediaQuery.of(context) bir istisna fırlatacaktır. Tüm InheritedWidget bağımlılıkları didChangeDependencies veya build'te ayarlanmalıdır.
Üçüncü hata, setState çağırmadan alanları değiştirmektir. Bir geliştirici setState olmadan bir State alanını değiştirirse, Flutter değişiklikten haberdar olmaz ve UI güncellenmez. Örneğin: sonrasında setState((){}) olmadan _list.add(item) listeyi değiştirir, ancak ekran aynı kalır.
State'te asenkron işlemler için güvenlik deseni:
Future<void> _fetchData() async {
final data = await ApiService.fetch();
if (mounted) {
setState(() => _data = data);
}
}
mounted kontrolü, setState'in yalnızca canlı bir State'te çağrılmasını sağlayarak “setState called after dispose” istisnasını önler.
Sıkça Sorulan Sorular
StatefulWidget değişmez bir widget yapılandırmasıdır, State ise verileri depolayan ve yaşam döngüsünü yöneten değişebilir bir nesnedir. Widget yeniden oluşturulabilir, State oluşturulamaz. StatefulWidget, createState aracılığıyla State oluşturur.
Tam olarak bir. createState yöntemi, StatefulWidget ilk kez ağaca eklendiğinde bir kez çağrılır. Ebeveyn birden çok kez yeniden yapılandırsa bile, widget türü veya Key değişmediği sürece State nesnesi aynı kalır.
mounted, State'in widget ağacında olup olmadığını gösteren bir boole işaretidir. dispose çağrısından sonra mounted false olur. İstisnaları önlemek için asenkron geri çağırmalarda setState'den önce kontrol için kullanılır.
Hayır. State her zaman generics aracılığıyla belirli bir StatefulWidget'a bağlıdır: State<T extends StatefulWidget>. Bir widget ile ilişkilendirme olmadan doğrudan State oluşturmak mimari olarak imkansızdır.
Bir istisna fırlatılır: “setState called after dispose”. dispose'dan sonra State ölü kabul edilir ve setState aracılığıyla UI'yı yeniden oluşturma girişimleri yasaktır. Çözüm, her setState'den önce mounted kontrol etmektir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun