setState tuzakları
- Flutter kursu
- Orta seviye
- Ders 3/99
- 4 dk
Async sonrası setState ve mounted kontrolünü öğrenirsin.
Async sonrası setState tuzağı
Bir Future bekledikten sonra setState çağırırsan, widget artık ekranda olmayabilir; kullanıcı başka sayfaya geçmiş olabilir. Bu durumda setState hata fırlatır.
Future.delayed(Duration(seconds: 2), () {
setState(() { _veri = 'hazır'; });
});Bunu önlemek için mounted kontrolü yaparsın.
mounted kontrolü
mounted, State nesnesinin o anda widget ağacında olup olmadığını söyler. true iken setState güvenlidir.
if (mounted) {
setState(() { _veri = sonuc; });
}dispose çağrıldıktan sonra mounted false olur.
Uygulama Async veri yükle ve mounted ile setState çağır
veriCek metodu 100 ms beklesin. Sonra if (mounted) kontrolü yapıp setState ile _veri'yi 'hazır' yap ve print(_veri) çağır.
Başlangıç kodu
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: VeriEkrani());
}
}
class VeriEkrani extends StatefulWidget {
@override
_VeriEkraniState createState() => _VeriEkraniState();
}
class _VeriEkraniState extends State<VeriEkrani> {
String _veri = 'yükleniyor';
@override
void initState() {
super.initState();
veriCek();
}
Future<void> veriCek() async {
await Future.delayed(Duration(milliseconds: 100));
// mounted kontrolü yap, setState ile veriyi güncelle ve ekrana yazdır
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text(_veri)),
);
}
}Örnek çözüm
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: VeriEkrani());
}
}
class VeriEkrani extends StatefulWidget {
@override
_VeriEkraniState createState() => _VeriEkraniState();
}
class _VeriEkraniState extends State<VeriEkrani> {
String _veri = 'yükleniyor';
@override
void initState() {
super.initState();
veriCek();
}
Future<void> veriCek() async {
await Future.delayed(Duration(milliseconds: 100));
if (mounted) {
setState(() {
_veri = 'hazır';
});
print(_veri);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text(_veri)),
);
}
}Beklenen çıktı
hazır
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Async bir işlem sonrası setState'ten önce ne yapılmalı?
- Async bir işlem sonrası setState'ten önce mounted kontrolü yapılır Doğru cevap
- mounted yalnızca initState içinde kullanılır
- mounted, State dispose edildikten sonra true olur
- mounted her zaman true'dur
Açıklama: Async sonrası widget ağaçtan çıkmış olabilir; setState'ten önce if (mounted) ile State'in hâlâ ağaçta olduğu kontrol edilir.
2 mounted kontrolünü ekle
Future<void> veriCek() async {
await Future.delayed(Duration(seconds: 1));
if (____) {
setState(() { _veri = 'hazır'; });
print(_veri);
}
}
Future<void> veriCek() async {
await Future.delayed(Duration(seconds: 1));
if (mounted) {
setState(() { _veri = 'hazır'; });
print(_veri);
}
}
Açıklama: Async sonrası setState'ten önce if (mounted) ile State'in hâlâ ağaçta olduğu doğrulanır; dispose edildiyse setState atlanır.
3 Async ve mounted parçaları
| Kavram | Anlamı |
|---|---|
mounted |
State'in widget ağacında olup olmadığı |
async |
Beklenebilen fonksiyonları işaretleyen anahtar kelime |
Future.delayed |
Belirli süre sonra callback çalıştırır |
if (mounted) |
Async sonrası setState'in güvenli çağrısı |