DEV Community

Cover image for Flutter State Yönetimi : Bölüm 1 💫 🌌 ✨
Gülsen Keskin
Gülsen Keskin

Posted on • Updated on

Flutter State Yönetimi : Bölüm 1 💫 🌌 ✨

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();
}

Enter fullscreen mode Exit fullscreen mode

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.

Image description
şekil 1

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.

Image description
şekil 2

  1. Constructor çağrılır.

  2. State nesnesi, ağaçta bir BuildContext veya konumla ilişkilendirilir. Widget artık "mounted" (monte edilmiş) olarak kabul edilir. Widget.mounted ile bir widget'ın takılı olup olmadığını kontrol edebilirsiniz.

  3. 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.

  4. 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, InheritedWidget içeren başlatmayı yapmanız gereken yerdir.

  5. 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.

  6. State nesnesi tamamen başlatılır ve State.build methodu çağrılır.

  7. 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(),
    ),
);

Enter fullscreen mode Exit fullscreen mode

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.

Image description

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;
Enter fullscreen mode Exit fullscreen mode

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);
  }
}

Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
ibrahimatmaca profile image
İbrahim Atmaca

Muhteşem gerçekten çok faydalı bir içerik olmuş

Collapse
 
gulsenkeskin profile image
Gülsen Keskin

Çok teşekkür ederim :) Çok sevindim :)