Volkan Gazioglu
3 min readJun 20, 2022

Psikoloji ve Flutter’ın setState yöntemi

Flutter, Google’ın yeni harika yazılım geliştirme teknolojisi, biliyorsunuz. Tek bir kod tabanı ile Android, iOS, Web, Linux, macOS, Windows ve Fuchsia için yazılım üretebiliyorsunuz.

Benim yazılımcı dashatar’ım (Dayanıklılık: 4, Çeviklik: 4, Bilgelik:2, Karizma:2)

Bugün sizlere, Flutter geliştirilirken yaşanılan bir olaydan bahsedeceğim. Belki de daha şimdiden milyonlarca kez kullanılmış olan bir yöntemin ortaya çıkış hikayesi ve bunun psikolojiyle bağlantısı.

Flutter’da her şey bir widget. Matruşka gibi düşünün. Widget’ler değişmez (immutable) ancak ekran çeşitli nedenlerle (parmaklarımız, animasyonlar, sensörler, internet alış-verişi vs) dinamik olarak değişmeli, değil mi??? O yüzden durum tutmayan (Stateless) widget’ların yanında bir de durum tutan (Statefull) widget lazım. Ekranda bir şey değişeceği zaman Flutter’ın ana çerçevesi, motoru (Engine) tarafından tetikleniyor ve meşhur ekrana resmetme (render) süreci başlıyor. State nesnesidir, element ağacıdır detaylara çok girmiyorum.

Solda durumsuz, sağda durumlu bir widget. Durumlu widget’ın şekilde görünmeyen bir durum (state) nesnesi de oluyor, durum burada tutuluyor.

Daha önceki bir makalemde bu işin 60 FPS, yani yaklaşık 1,6 ms de bir yapıldığını anlatmıştım (https://gazioglu.medium.com/flutter-ve-60-fps-3b748204b54a).

İşte bu durum tutan widget’ların kendine özgü bir yaşam döngüsü ve bu döngü içerisinde de, “Hadi şuranın havasını değiştirilelim” diyen bir yöntem var: ünlü setState. Değişiklik ihtiyacında bu yöntemi çağırıyoruz, o da sağolsun işleri hallediyor. Di mi? Yok yok, aslında setState’in pek de bir şey yaptığı yok.

Flutter’ın çalışma yöntemi, her bir ekran tazeleme dönemi için nelerin değişeceğini hesaplama üzerine kurulu. Yani, bir widget’ı “Bu kirlendi” 💩diye işaretledin mi o ve altı tekrar üretime giriyor.

2017'de Flutter ekibi; geliştirici UX çalışmaları yaparken, yazılımcıları bir saatliğine kendi başlarına bırakmışlar. O zamanlar bu iş için “markNeedsBuild” yöntemi öneriliyormuş. Ancak geliştiriciler bu yöntemi ne zaman kullanacakları konusunda tam emin olamışlar. Böyle dört yapraklı yonca muamelesi görmüş 🍀

@protected
void setState(VoidCallback fn) {
final dynamic result = fn() as dynamic;
_element.markNeedsBuild();
}

Ekip karar vermiş, callback’li senkron bir şekilde çağrılan setState’i kullanmaya. İşler böylece bugünlere gelmiş. Hem sonra kafamızda “Bu Mark kim, nereli, neden bu build’e ihtiyaç duruyor?” gibi garip sorulara da gerek kalmamış oluyor 😅 VoidCallback dediğin de bir typedef’den ibaret.

typedef VoidCallback = void Function();

Şimdi size çok basit bir uygulama ile durumsuz bir widget ile setState kullanımını göstereceğim, evde yapmaya kalkmayın!

Evde denemeyin!
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: FlutterCokIyiGelsene(),));
}
class FlutterCokIyiGelsene extends StatelessWidget {
var anahtar = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Durumsuzuz')),
body: Container(
child: Center(
child: GestureDetector(
child: Container(
color: anahtar ? Colors.yellow: Colors.red,
),
onTap: () {
anahtar = !anahtar;
(context as Element).markNeedsBuild();
}),
),
),
);
}
}

Her widget bir eleman oluşturuyor. Aslında herkesin dediği gibi bir widget ağacı yok, elemanlar ağacı var. Kirli olarak işaretlenen widget yeniden oluşturuluyor. Tabi durumlu bir widget, çok detaya girmemiştim, kendi durum (State) nesnesini oluşturuyor. E başka türlü ekranı nasıl değiştireceğiz? Üstelik değişmez bir widget’ı alıp-satmak çok ucuz, siz de olsanız böyle yapardınız.

Yukarıdaki kodda uygunsuz bir durum var farkedebildiniz mi bu arada? Üşendiğimden yapmıştım ama sonra iyi bir örnek olduğunu farkedince bıraktım. “anahtar” final olmalı, değişmez olmalı. Ben ne yapmışım? Skandal!

Çok teknoloji gördük, büyük umutlarla gelen, bazıları da harikaydı. Kimi tuttu, kimi öldü gitti. Flutter tutarsa yazılım dünyasında önemli bir dönüm noktası olur. Öğrenmeye değer. Flutter’lı günler dilerim.