Bölüm içeriği
🦋 StatefulWidget
🦋 Widget tree ve element tree
🦋 lifecycle methodları
🦋 InheritedWidget
StatefulWidget
Bir StatefulWidget'ın iki görevi vardır: tıpkı bir StatelessWidget gibi immutable (değişmez) değişkenleri tutmak ve ilişkili bir state nesnesi oluşturmaktır.
StatefulWidget örneği:
class ItemCounter extends StatefulWidget {
final String name;
ItemCounter({this.name});
@override
_ItemCounterState createState() =>
_ItemCounterState();
}
Bir state nesnesinin temel işi, internal (mutable) (dahili (değişken)) bir durumu takip etmek ve State.build ile alt widget'lar oluşturmaktır.
Widget tree ve element tree
Flutter, element ağacını oluşturarak widget'ların ekrana nasıl işleneceğini bilir. Widget ağacı doğrudan render edilmez, çünkü widget'lar render edilebilir elementler için "planlar"dır.
Element tree (şekil 1), stateful widget'ları aynı şekilde işlemez.
StatefulWidget ağaçta değiştirilirse, yeni widget aynı türdedir (ve aynı anahtara sahiptir) karşılık gelen element, ağaçta aynı noktayı işaret etmeye devam eder ve yeni stateful widget'a başvurur, ancak ilişkili state nesnesi olduğu yerde kalır ve yeniden kullanılır.
Flutter, state nesnesi üzerinde, element ağacındaki değişikliklere yanıt vermenize olanak tanıyan methodlar sağlar. Bu methodlar belirli bir sırayla çağrılır ve widget'ın yaşam döngüsü (lifecycle) olarak adlandırılırlar.
StatefulWidget yaşam döngüsü ve ne zaman ne yapılacağı
Şekil 2, yaşam döngüsünü sırayla gösterir.
Constructor çağrılır.
State nesnesi, ağaçta bir
BuildContextveya konumla ilişkilendirilir. Widget artık "mounted" (monte edilmiş) olarak kabul edilir.Widget.mountedile bir widget'ın takılı olup olmadığını kontrol edebilirsiniz.State.initStateçağrılır. Bu method tam olarak bir kez çağrılır. ve stateful widget'a veya build context'e bağlı olan State nesnesindeki özellikleri başlatmak için kullanılır.State.didChangeDependenciesçağrılır. Bu yöntem özeldir, çünkü initState'den hemen sonra bir kez çağrılır, ancak yaşam döngüsünün ilerleyen kısımlarında da çağrılabilir. Bu method,InheritedWidgetiçeren başlatmayı yapmanız gereken yerdir.Bu noktada state "dirty" kabul edilir ve bu sayede Flutter hangi widget'ların yeniden oluşturulması gerektiğini takip edebilir. İlk kez de dahil olmak üzere, bir state nesnesi oluşturulması gerektiğinde, kendisini dirty olarak işaretler.
State nesnesi tamamen başlatılır ve
State.buildmethodu çağrılır.Yeni bir build'den sonra state "clean" olarak işaretlenir. State nesnesi amaçlandığı gibi görüntülenir ve framework'ün kendisine daha fazla talimat vermesini bekler. Bu durumda birkaç şey olabilir:
•state.setState, state'i her zaman dirty olarak işaretleyen kodunuzdan çağrılır.
• Bir ancestor widget, ağaçtaki bu konumun yeniden oluşturulmasını isteyebilir. Konum aynı widget türü ve anahtarıyla yeniden oluşturulacaksa, framework argüman olarak önceki widget'la didUpdateWidget'ı çağırır. Bu aynı zamanda state'i dirty olarak işaretler ve böylece state yeniden inşa edilir.
• Widget'ınız bir InheritedWidget'a bağlıysa ve inherited widget değişirse, framework didChangeDependencies öğesini çağırır. Bu noktada, widget yeniden oluşturulacaktır.
• State nesnesinin ağaçtan kaldırılması için State.disposed çağrılır. Bu method, etkin animasyonları durdurmak veya akışları(streams) kapatmak gibi widget tarafından kullanılan kaynakları temizlemeniz gereken yerdir. disposed bir kez çağrıldığında, widget bir daha asla oluşturamaz. Bu noktada setState'i çağırmak bir hatadır.
Flutter'daki tüm yeniden oluşturmalar, State nesnesine ve yaşam döngüsüne (lifecycle) bağlıdır.
InheritedWidget
Inherited widget'ları muhtemelen daha önce görmüşsünüzdür: Tema, MediaQuery ve Scaffold'un tümü inherited'dır. Inherited widget'ın alt ağacındaki herhangi bir widget, inherited widget'a erişebilir ve geliştirme sırasında widget'ları ağaç etrafında taşımak istiyorsanız, diğer widget'ların kodunu değiştirmeniz gerekmez.
InheritedWidget sınıfının belgelerine bakarsanız, bunun üçüncü bir widget türü olduğunu ve daha da önemlisi stateful widget sınıfının bir uzantısı olmadığını görürsünüz. Bu widget "bilgiyi ağaçta verimli bir şekilde yayan widget'lar için temel bir sınıftır."
Bu, merkezi bir depolama olarak çalışmasını sağlamak için stateful widget'ı bir inherited widget'la birleştirmeniz gerektiği anlamına gelir.
runApp(
AppStateContainer(
blocProvider: blocProvider,
child: ECommerceApp(),
),
);
Koddaki AppStateContainer sınıfı, bir StatefulWidget'tır ve state.build methodu, bir InheritedWidget geçer.
Widget ağacınızda bir inherited widget'tan bilgi almak istiyorsanız, muhtemelen o inherited widget'a of adlı bir methodla başvuru sağlarsınız. Bu method ağaca bakar ve o türden en yakın parent inherited widget'ı bulur.
Bir InheritedWidget kullanarak, of methoduyla ağaçta daha yüksekteki widget'lara referanslar alabilirsiniz.
of methodlarının çoğu, inherited widget'ların kendisinde tanımlanır ve sağladığınız BuildContext ile BuildContext.inheritFromWidgetOfExactType'ı çağırır.
Bu method statik olduğundan, sınıfın bir örneğine herhangi bir başvuru yapılmadan herhangi bir yerden çağrılabilir.
updateShouldNotify methodu
Inherited widget yeniden oluşturulduğunda, verilerine bağlı olan tüm widget'lara da yeniden oluşturmalarını söylemesi gerekebilir. Bu method, yeniden oluşturmalardan sonra çağrılır ve her zaman eski widget'a bir argüman olarak geçer. Bu size Flutter'ın yeniden inşa edilip edilmeyeceğini (rebuilt) kontrol etme şansı verir.
bool updateShouldNotify(_AppStoreContainer oldWidget) =>
oldWidget.appData != this.appData;
Ağacın tepesinde inherited widget kullanmak, bir bakıma state'i yukarı kaldırmanın daha temiz bir tarzıdır. Bu yöntemi kullanarak, setState yöntemlerinizin tümü AppState durum nesnesinde yaşayabilir ve bunları AppState.of(context).callMyMethod() kullanarak çağırabilirsiniz.
Inherited widget'ın state'ini değiştiren herhangi bir method çağrıldığında, değişikliğin ağacın aşağısındaki widget'larda yeniden oluşturmaları tetikleyip tetiklemeyeceğini bilmesi gerekir.
class AppState extends State<AppStateContainer> {
BlocProvider get blocProvider => widget.blocProvider;
// ... build methodu ve diğer sınıf üyeleri
// 'LIFTING STATE UP' REGION:
int cartCount = 0;
void updateCartCount(int count) {
setState(() => cartCount += count);
}
}
AppState.setState çağrıldığında kendini yeniden oluşturur. Bu, inherited child widget'ın yeniden oluşturulmasına neden olur ve ardından dahili olarak updateShouldNotify öğesini çağırır. Bu true ise, inherited widget bileşenine bağlı state bilgisi olan widgetlarda didChangeDependencies çağrılır ve ardından widgetlar yeniden oluşturulur.
Bi sonraki bölümde BLoC modelini öğreneceğiz.. :) 🦋
Resources:
• Flutter In Action Chapter:8
• https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html



Top comments (2)
Muhteşem gerçekten çok faydalı bir içerik olmuş
Çok teşekkür ederim :) Çok sevindim :)