Widget Tree, Flutter'da kullanıcı arayüzünün düzenini tanımlayan hiyerarşik bir widget yapısıdır. Bir düğmeden tüm ekrana kadar arayüzün her öğesi, bir üst kapsayıcı içinde iç içe geçmiş ayrı bir widget ile temsil edilir. Flutter, her durum değişikliğinde Widget Tree'yi günceller — çerçeve yeni ve eski ağacı karşılaştırır ve minimum değişiklik uygular. Flutter Team, 2025'e göre, verimli bir ağaç yapısı animasyonların akıcılığını ve arayüz yanıt verme hızını doğrudan etkiler.
Önemli Noktalar
Widget Tree, Flutter'da kullanıcı arayüzünün bildirimsel bir tanımıdır ve iç içe geçmiş widget'lardan oluşan bir ağaç olarak inşa edilir. Her widget, UI'nin bir bölümünü tanımlar: yapılandırması, görüntüleme parametreleri ve etkileşim sırasındaki davranışı. Geliştirici, mevcut uygulama durumunda arayüzün nasıl görünmesi gerektiğini tanımlar ve Flutter bu tanımı ekrandaki piksellere dönüştürmeyi üstlenir.
Geliştiricinin arayüz öğelerini doğrudan manipüle ettiği emir kipi çerçevelerinin aksine, Flutter bildirimsel bir yaklaşım kullanır. Uygulama durumu değiştiğinde yeni bir Widget Tree oluşturulur ve çerçeve eski ile yeni ağaç arasındaki farkı hesaplar. Bu, oluşturma işlemlerinin sayısını en aza indirir ve kodu daha öngörülebilir hale getirir.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Widget Tree")),
body: Center(
child: Column(
children: [
Text("Merhaba, Flutter"),
ElevatedButton(
onPressed: () {},
child: Text("Bana bas"),
),
],
),
),
),
);
}
}
Bu örnekte Widget Tree, MaterialApp, Scaffold, AppBar, Center, Column, Text ve ElevatedButton'dan oluşur. Bu widget'ların her biri ağaçta bir düğümdür. Uygulama durumu değiştiğinde Flutter, build yöntemini yeniden çağırır ve sonucu önceki ağaçla karşılaştırır.
Widget Tree, runApp yöntemine iletilen bir kök widget ile başlar. Kök widget genellikle MaterialApp, CupertinoApp veya WidgetsApp'tir — uygulamanın genel ayarlarını belirler. Kökten ağaç, her biri kendi alt öğelerini içerebilen alt widget'lara dallanır.
Flutter'daki widget'lar tek-alt (single-child) (child parametresi aracılığıyla bir alt öğe kabul eder) ve çoklu-alt (multi-child) (children aracılığıyla bir alt öğe listesi kabul eder) olarak ikiye ayrılır. Tek-alt örnekleri: Center, Padding, SizedBox, Container. Çoklu-alt: Column, Row, Stack, ListView, GridView. Bu fark, Widget Tree yapısını etkiler: çoklu-alt widget'lar daha geniş ağaçlar oluştururken, tek-alt widget'lar daha derin ağaçlar oluşturur.
BuildContext, Widget Tree'de bir widget'ın konumudur. Her widget'ın kendi BuildContext'i vardır, bu build yöntemine iletilir ve üst widget'lara, temaya, MediaQuery'ye ve diğer InheritedWidget'lara erişmek için kullanılır. BuildContext, widget ile Element Tree'deki öğesi arasında bir köprü görevi görür.
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final mediaQuery = MediaQuery.of(context);
return Container(
color: theme.colorScheme.primary,
child: Text(
"Ekran genişliği: ${mediaQuery.size.width}"
),
);
}
}
Bu örnekte, BuildContext tema ve ekran boyutlarını almak için kullanılır. Flutter, InheritedWidget olan en yakın Theme ve MediaQuery'ye kadar Widget Tree'de yukarı çıkar. Bu, bağlamın bir widget'ı hiyerarşideki konumuna nasıl bağladığını gösterir.
Bir Flutter uygulaması başlatıldığında, kök widget'ı alan ve Widget Tree'yi oluşturmaya başlayan runApp işlevi çağrılır. Süreç üç aşamadan oluşur: widget yapılandırması oluşturma, Element Tree'yi oluşturma ve gerçek oluşturma için RenderObject Tree'yi inşa etme.
runApp işlevi, çerçeveyi grafik motoruna bağlayan WidgetsFlutterBinding aracılığıyla bir kök öğe oluşturur. Kök widget ağaca yerleştirilir ve Flutter, onu alt widget'larla doldurmak için build yöntemini çağırır. Her build çağrısı, Widget Tree'nin yeni bir alt grafiğini oluşturur.
Widget Tree'yi oluşturduktan sonra Flutter, tüm widget'ların boyutlarını ve konumlarını hesaplayan bir ilk düzen gerçekleştirir. Bu süreç kökten başlar ve ağaçta aşağı doğru yayılır. Her widget, üst öğesinden kısıtlamalar alır ve hesaplanmış bir boyut döndürür. Boyutlar eşleşmezse Flutter bir düzen hatası oluşturur.
Düzen tamamlandıktan sonra Flutter, her widget'ı oluşturmaya devam eder. RenderObject, arayüz tanımını GPU tarafından Skia veya Impeller aracılığıyla yürütülen grafik komutlarına dönüştürür. Widget Tree'den piksellere kadar tüm süreç, saniyede 120 kareye kadar her durum değişikliğinde tekrarlanır.
StatelessWidget, iç değişebilir durumu olmayan bir widget'tır. Görünümü tamamen kurucu aracılığıyla iletilen giriş parametreleri tarafından belirlenir. Parametreler değişmediyse StatelessWidget yeniden oluşturulmaz. Bu, onu performans açısından hafif yapar.
Simgeler, metin etiketleri, dekoratif ayırıcılar ve iç mantığı olmayan basit düğmeler gibi statik arayüz öğeleri için StatelessWidget kullanın. Flutter dokümantasyonuna göre, tipik bir uygulamadaki widget'ların yaklaşık %70'i StatelessWidget olabilir, bu da çöp toplayıcı yükünü azaltır ve yeniden oluşturmaları hızlandırır.
StatefulWidget, widget yeniden oluşturmaları arasında kalıcı olan bir State nesnesi oluşturur. Durum değiştiğinde (setState aracılığıyla), Flutter widget'ı “kirli” olarak işaretler ve bir sonraki karede yeniden oluşturur. StatefulWidget, etkileşimli öğeleri (giriş alanları, animasyonlar, zamanlayıcılar ve dinamik listeler) mümkün kılar.
class CounterWidget extends StatefulWidget {
@override
State<CounterWidget> createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text("Sayı: $_count"),
ElevatedButton(
onPressed: () {
setState(() => _count++);
},
child: Text("Artır"),
),
],
);
}
}
Bu örnekte, StatefulWidget sayacı güncellemek için setState kullanır. Durum güncellendiğinde Flutter, Widget Tree'nin yalnızca değişen kısmını — CounterWidget ve alt öğelerini — yeniden oluşturur. Üst widget'lar yeniden oluşturulmaz, bu Flutter'ın bildirimsel modelinin önemli bir avantajıdır.
Widget Tree yapılandırma katmanıdır, Element Tree ise widget'lar ile gerçek oluşturma arasındaki ara bağlantıdır. Widget Tree'deki her widget, Element Tree'de widget'a bir referans depolayan ve yaşam döngüsünü yöneten bir öğe oluşturur. Bu mimari, Flutter'ın değişiklikleri verimli bir şekilde ele almasını sağlar.
Flutter bir widget ile ilk karşılaştığında, karşılık gelen bir öğe oluşturan createElement yöntemini çağırır. StatelessWidget için StatelessElement oluşturulur; StatefulWidget için StatefulElement oluşturulur ve bu ayrıca bir State nesnesi oluşturur. Öğe, widget yeniden oluşturulsa bile yeniden oluşturma döngüleri arasında kalıcı olur.
Key, Flutter'ın eski ve yeni Widget Tree'den widget'ları eşleştirmesine yardımcı olan bir tanımlayıcıdır. Bir widget'ın Key'i varsa Flutter, ağaçtaki konumu yerine karşılık gelen öğeyi bulmak için bunu kullanır. Öğelerin sırasının değişebileceği dinamik listelerle çalışırken anahtarlar gereklidir.
ListView(
children: items.map((item) => ListItem(
key: ValueKey(item.id),
data: item,
)).toList(),
)
Key olmadan Flutter, öğeleri konuma göre eşleştirir; bu, sıra değiştiğinde yanlış durum korumaya yol açabilir. Benzersiz tanımlayıcıya sahip ValueKey, her öğenin listedeki konumundan bağımsız olarak durumunu korumasını sağlar.
Widget Tree yapısı, Flutter uygulamasının performansını doğrudan etkiler. İç içe geçmiş birçok widget'a sahip derin ağaçlar, düzen aşaması için daha fazla zaman gerektirir ve bellek kullanımını artırır. Flutter DevTools, Widget Tree'yi analiz etmek ve darboğazları belirlemek için araçlar sağlar.
Her iç içe geçme seviyesi, düzen ve boyama sırasında ek hesaplamalar ekler. Derin zincir iç içe geçme yerine daha düz yapılar kullanın. Örneğin, Expanded ile Row, Align ile birden çok iç içe Container'ın yerini alabilir. Flutter Team'e göre ağaç optimizasyonu, düzen süresini %40'a kadar azaltabilir.
Flutter DevTools, mevcut Widget Tree'yi gerçek zamanlı olarak gösteren “Widget Inspector” aracını sağlar. Geliştirici, ekrandaki herhangi bir widget'ı seçebilir ve ağaçtaki yerini, parametrelerini ve düzen kısıtlamalarını görebilir. Bu, beklenmeyen iç içe geçmeyi, aşırı yeniden oluşturmaları ve boyutlandırma sorunlarını belirlemeye yardımcı olur.
RepaintBoundary, bağımsız oluşturma için Widget Tree'nin bir bölümünü izole eden bir widget'tır. RepaintBoundary içindeki içerik değişirse, tüm ekran değil yalnızca kendi alanı yeniden boyanır. Animasyonlar, listeler ve sık güncellenen diğer öğeler için RepaintBoundary kullanın.
RepaintBoundary(
child: CustomPaint(
painter: MyPainter(),
child: SizedBox(
width: 200,
height: 200,
),
),
)
Bu örnekte, RepaintBoundary CustomPaint'i ayrı bir oluşturma alanına izole eder. Bu alan içindeki animasyon güncellendiğinde, yalnızca CustomPaint widget'ı yeniden boyanır, ekranın geri kalanı değişmez. Bu, birden çok animasyonlu öğeye sahip karmaşık arayüzlerde özellikle kullanışlıdır.
Sıkça Sorulan Sorular
Widget Tree, her yeniden oluşturmada yeniden oluşturulan bildirimsel bir arayüz tanımıdır. Element Tree güncellemeler arasında kalıcı olur ve widget'ların gerçek RenderObject'lerle yaşam döngüsünü, durumunu ve eşlemesini yönetir.
Widget sayısında bir sınır yoktur, ancak pratikte binlerce widget içeren bir ağaç düzen aşamasını yavaşlatabilir. Flutter, birkaç bin düğüme kadar olan ağaçlar için optimize edilmiştir; daha büyük sayılar için ListView.builder aracılığıyla sanallaştırma önerilir.
Flutter DevTools — “Widget Inspector” sekmesini kullanın. Uygulamayı hata ayıklama modunda çalıştırın, tarayıcıda DevTools'u açın ve Widget Tree'deki yerini görmek için ekrandaki herhangi bir widget'ı seçin.
Yeniden oluşturma, durum değiştiğinde widget yapılandırmasını yeniden oluşturma sürecidir. Flutter, değişen widget'lar için build yöntemini yeniden çağırır, yeni Widget Tree'yi öncekiyle karşılaştırır ve Element Tree'ye minimum değişiklik uygular.
İç içe geçme derinliğini azaltın, statik öğeler için const widget'lar kullanın, animasyonları izole etmek için RepaintBoundary uygulayın ve StatelessWidget'ın yeterli olduğu yerlerde aşırı StatefulWidget'lardan kaçının.
Ö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