Flutter'ın Pusulası: BuildContext Nedir ve Neden Hayatidir?
Flutter ile uygulama geliştirirken Widget build(BuildContext context) satırını binlerce kez yazarız. Peki, her build metodunda bize parametre olarak verilen bu context aslında nedir? Sadece bir parametre mi, yoksa uygulamanın "sinir sistemi" mi?
1. BuildContext Nedir? (Basit Analoji)
En basit tabiriyle BuildContext, bir Widget'ın widget ağacı içerisindeki "konumunu" (adresini) ve "kimliğini" temsil eden bir referanstır.
Bunu bir apartman dairesine benzetebiliriz:
Widget: Dairenin planı (mutfak nerede, salon kaç metrekare).
BuildContext: Dairenin apartmandaki tam adresi (Kat 3, Daire 5).
Siz "Bana en yakın yangın merdivenini (Theme veya Navigator) bul" dediğinizde, apartman görevlisi (Flutter Framework) sizin hangi dairede olduğunuza (Context) bakar ve ona göre size en yakın çıkışı gösterir.
2. Perde Arkası: Widget, Element ve RenderObject
BuildContext'i tam anlamak için Flutter'ın "Üçlü Ağaç" yapısını hatırlamak gerekir.
Widget Ağacı: Sizin yazdığınız kodlar. (Sadece bir konfigürasyondur, hafiftir, sürekli yok olup yeniden oluşturulur.)
Element Ağacı: Widget'ların hayata geçmiş halidir. Aslında BuildContext, teknik olarak Element'in ta kendisidir.
Render Ağacı: Ekrana çizim yapan yapıdır.
Kritik Bilgi: BuildContext aslında Element sınıfından türetilmiş bir arayüzdür. Yani context dediğimizde, o widget'a karşılık gelen Element nesnesine erişmiş oluruz. Bu sayede ağaçta yukarıya doğru bakıp "Benim atalarım kim?", "Hangi temayı kullanmalıyım?" sorularını sorabiliriz.
3. BuildContext Ne İşe Yarar?
Context, ağaç üzerinde yukarıya doğru (ancestors) arama yapmamızı sağlar. Flutter'da veri akışı genellikle yukarıdan aşağıya olsa da, verilere erişim context üzerinden yukarıya doğru yapılır.
En sık kullandığımız senaryolar:
A. Navigasyon İşlemleri
Yeni bir sayfaya gitmek istediğinizde, Flutter'ın "Hangi sayfadayım ki yenisini onun üzerine koyayım?" sorusuna context ile cevap veririz.
// Context, şu anki konumuzu belirtir.
Navigator.of(context).push(MaterialPageRoute(...));
B. Tema ve Medya Sorguları (InheritedWidget)
Ekran boyutunu öğrenmek veya genel renk paletine erişmek için ağacın en tepesindeki verilere context aracılığıyla ulaşırız.
// Ağaçta yukarı çık, en yakın Theme verisini bul ve getir.
final renk = Theme.of(context).primaryColor;
// Ağaçta yukarı çık, ekran boyutlarını (MediaQuery) bul.
final genislik = MediaQuery.of(context).size.width;
4. En Sık Yapılan Hata: "BuildContext Across Async Gaps"
Geliştiricilerin, özellikle de yeni başlayanların en çok başını ağrıtan konu: Asenkron işlemlerden sonra context kullanımı.
Senaryo:
Bir butona bastınız, internetten veri çektiniz (3 saniye sürdü) ve sonra bir uyarı (Dialog) göstermek istediniz.
onPressed: () async {
await veriyiCek(); // 3 saniye süren işlem
// HATA RİSKİ!
// Bu 3 saniye içinde kullanıcı sayfadan çıkmış olabilir.
// Sayfa yoksa, "context" de artık geçersizdir (unmounted).
showDialog(context: context, ...);
}
Sorun: Asenkron işlem bittiğinde, eğer kullanıcı o ekranı kapatmışsa, elinizdeki context artık "ölü" bir widget'a aittir. Ölü bir widget üzerinde işlem yapmaya çalışmak uygulamanın çökmesine veya hatalara neden olur.
Çözüm: mounted Kontrolü
Flutter'da işlem yapmadan önce widget'ın hala ekranda olup olmadığını (mounted) kontrol etmeliyiz.
onPressed: () async {
await veriyiCek();
// Eğer widget hala hayattaysa devam et
if (!context.mounted) return;
showDialog(context: context, ...);
}
5. Doğru Context'i Kullanmak: "Scaffold Nerede?"
Bazen Scaffold içinde bir SnackBar göstermek istersiniz ama Flutter "Scaffold bulunamadı" hatası verir.
Hatalı Kod:
class AnaSayfa extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ElevatedButton(
onPressed: () {
// BURADAKİ context, AnaSayfa'nın context'idir.
// Scaffold henüz oluşturulma aşamasındadır, ağaçta bu context'in üstünde değildir.
ScaffoldMessenger.of(context).showSnackBar(...);
},
child: Text("Göster"),
),
);
}
}
Çözüm: Builder widget'ı kullanarak yeni bir alt context oluşturmak.
Scaffold(
body: Builder(
builder: (BuildContext yeniContext) {
return ElevatedButton(
onPressed: () {
// Artık Scaffold, yeniContext'in üstündedir.
ScaffoldMessenger.of(yeniContext).showSnackBar(...);
},
...
);
},
),
)
Özet
Konum Belirleyicidir: BuildContext, widget'ın ağaçtaki yerini gösterir.
Veri Taşıyıcıdır: Tema, Navigasyon ve Ekran boyutu gibi verilere ulaşmamızı sağlayan anahtardır.
Element'in Kendisidir: Widget ile RenderObject arasındaki köprüdür.
Canlı Olmalıdır: Asenkron işlemlerden sonra mutlaka
mountedkontrolü yapılmalıdır.
BuildContext kavramını iyi anlamak, Flutter'da karşılaşılan hataların %50'sini daha oluşmadan çözmek demektir.
BuildContext Nedir?
BuildContext, Flutter’da bir widget’ın widget ağacındaki (Widget Tree) konumunu temsil eden bir referanstır.
Basit tanım:
BuildContext = “Bu widget, uygulamanın neresinde duruyor?” sorusunun cevabıdır.
Widget build(BuildContext context) {
return Text("Merhaba");
}
Buradaki context:
Widget’ın
Hangi parent altında olduğunu
Hangi theme, media, navigator vb. verilere erişebileceğini bilir
BuildContext Neden Gereklidir?
BuildContext sayesinde:
✅ Tema bilgisine erişiriz
✅ Ekran boyutunu öğreniriz
✅ Sayfalar arası geçiş yaparız
✅ Snackbar, dialog, bottomSheet açarız
✅ InheritedWidget / Provider / Bloc verilerini okuruz
Widget Tree & BuildContext İlişkisi
Flutter uygulaması ağaç (tree) yapısındadır:
MaterialApp
└── Scaffold
└── Column
├── Text
└── ElevatedButton
Her widget:
Kendi BuildContext’ine sahiptir
Parent–child ilişkisini bu context üzerinden bilir
📌 Önemli:
Context widget’ın kendisi değil, widget’ın ağaçtaki konumudur.
BuildContext Nereden Gelir?
4.1 StatelessWidget
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text("Merhaba");
}
}
4.2 StatefulWidget
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
return Text("Merhaba");
}
}
📌 context, build metodu çağrıldığında otomatik verilir.
BuildContext ile Theme Kullanımı
Text(
"Merhaba",
style: Theme.of(context).textTheme.titleLarge,
);
Burada:
Theme.of(context)En yakın Theme widget’ını yukarı doğru arar
MediaQuery & Ekran Bilgisi
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
Kullanım alanları:
Responsive tasarım
Tablet / telefon ayrımı
Dinamik boyutlandırma
Navigator & Sayfa Geçişleri
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondPage()),
);
📌 Navigator:
Context üzerinden
En yakın
Navigatorwidget’ını bulur
SnackBar, Dialog ve BottomSheet
SnackBar
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Kaydedildi")),
);
AlertDialog
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Uyarı"),
content: Text("Silmek istiyor musunuz?"),
);
},
);
📌 Yanlış context kullanılırsa çalışmaz veya hata verir.
En Sık Yapılan BuildContext Hataları
❌ initState içinde context kullanmak
@override
void initState() {
super.initState();
Theme.of(context); // HATA
}
✅ Doğru kullanım:
@override
void didChangeDependencies() {
super.didChangeDependencies();
Theme.of(context); // DOĞRU
}
❌ Yanlış parent context kullanımı
Scaffold.of(context).openDrawer(); // HATA
Çözüm:
Builder(
builder: (context) {
return IconButton(
icon: Icon(Icons.menu),
onPressed: () {
Scaffold.of(context).openDrawer();
},
);
},
);
Builder Widget ve Yeni Context
Builder(
builder: (BuildContext newContext) {
return Text("Yeni Context");
},
);
Builder:
Yeni bir context üretir
Parent’a bağlı hataları çözer
InheritedWidget, Provider ve Context
Provider.of<User>(context);
context.read<User>();
context.watch<User>();
📌 Bu yapılar:
Veriyi context üzerinden
Widget tree boyunca taşır
BuildContext Yaşam Döngüsü
| Aşama | Context Durumu |
|---|---|
| initState | ❌ Kullanılamaz |
| didChangeDependencies | ✅ Kullanılabilir |
| build | ✅ Kullanılabilir |
| dispose | ❌ Kullanılmaz |
BuildContext = Widget Değildir!
❌ Yanlış düşünce:
“Widget = Context”
✅ Doğru:
Widget → BuildContext → Element → RenderObject
Ders İçin Özet
📌 BuildContext:
Widget’ın ağaçtaki adresidir
Flutter’ın kalbidir
Yanlış kullanılırsa en çok hata alınan konudur
📌 Öğrenciler için ipucu:
“Context soruyorsa: Bu widget nerede? diye sor”
Yorumlar
Yorum Gönder