Merhabalar, bad state hatası alıyorum çünkü value null geliyor. Hot reload yapıyorum ve hata düzeliyor, sorunsuz bir şekilde çalışıyor. Hatayı sadece başlangıçta veriyor. Araştırdığımda setState ile bu hatayı gidermişler fakat bende işe yaramadı ya da ben yapamadım bilemiyorum. Bu hatanın başka bir çözümü var mıdır?

  • HseyinAkkaya replied to this.
    • Erdem olmazsınız. İnitstate sayfa ilk açılırken bir kez tetiklenir. Daha sonra Build tetiklenir. Sonrasında her setstate yaptığında build tekrar tetiklenir ama initstate tetiklenmez. Şöyle düşün. Sayfa açılırken internetten 20Mb bir veri çekiyosun diyelim çok büyük bir veri. Sonra bunu ekranda gösteriyosun diyelim. Her setstate yaptığında bu 20Mb verinin tekrar tekrar inmesini mi isteriz, yoksa sadece yaptığımız değişikliği mi görmek isteriz?
      Build içinde atama yapmaktan kaçının.

      Field oluştur
      İnitstate içinde değerini ata
      Build içinde göster

      Ayrıca bir diğer sorun getLocation async bir metod. Başında await kullanmalısınız. İnitstate içinde await kullanamazsınız. Dolayısıyla then içinde setstate kullanarak ekranı yenilemelisiniz.

    Erdem değer için null kontrolü yapın. Örneğin build içinde değer null ise return circularprogressindicator kullanın. değil ise sayfa normal build edilsin. Daha sonra değişkenin doldurulduğu kısımda setstate kullanın. Böylece değer ilk başta null geldiğinde ekranda yüklenme ekranı görünecek. değer atandıktan sonra setstate ile sayfa tekrar build edilip normal değerler ile oluşturulacaktır. Kod atsanız daha sağlıklı cevap verebilirdik. Ancak temel mantık bu şekilde.

    12 days later

    HseyinAkkaya Mesajınızı daha yeni gördüm.
    `class RainyPage extends StatefulWidget {
    const RainyPage({Key? key}) : super(key: key);

    @override
    _RainyPageState createState() => _RainyPageState();
    }

    class _RainyPageState extends State<RainyPage> {
    WeatherPage weat = WeatherPage();
    late String admin, des, temp, hum, wind;
    @override
    Widget build(BuildContext context) {
    weat.getLocation();
    setState(() {
    admin = weat.adminArea.toString();
    des = weat.data.first.weatherDescription.toString();
    temp = weat.data.first.temperature.toString();
    hum = weat.data.first.humidity.toString();
    wind = weat.data.first.windSpeed.toString();
    });
    return WeatherScreenModel(
    3, admin, CustomColors.rainBlue, des, const Rain(), temp, hum, wind);
    }
    }`

    Classtaki kod bu şekilde. Hot reload yapmadan bilgiler gelmiyor. Bad state kırmızı ekranında kalıyor. Setstate kulanımı yanlış büyük ihtimalle

    Erdem kullanımınızda şöyle bir sıkıntı var. Build içerisi setstate ile tekrar tetiklenir. Dolayısıyla değerleri yeniden atamaya çalışıyorsunuz. Bunun yerine build içerisinde sadece return kısmını bırakın. Atamaları initstate içerisine taşıyın. Eğer getLocation metodu bir feature metod ise await veya then ile kullanmanız gerek. Aksi takdirde sonuç beklenmeden setstate çağırmış olursunuz. Sonuç geldiğinde ekran çoktan oluşturulmuş olur.

    Peki return kısmında neyi return edeceğim yani atamayı initstate de yaparsam boş bir field return etmiş olmaz mıyım?

    bilgilerin alındığı class bu
    `class WeatherPage {
    String? country, adminArea;
    List<Weather> data = [];
    late WeatherFactory wf;

    void getLocation() async {
    final service = LocationService();
    final locationData = await service.getLocation();
    if (locationData ≠ null) {
    final placeMark = await service.getPlaceMark(locationData: locationData);
    country = placeMark?.country ?? ‘could not get country’;
    adminArea = placeMark?.administrativeArea ?? ‘could not get admin area’;
    }
    wf = WeatherFactory(“eefd4c0e4119d1ba50c49d9acf649059”,
    language: Language.TURKISH);
    Weather weather = (await wf.currentWeatherByCityName(adminArea!));
    data = [weather];
    }
    }`

      Erdem olmazsınız. İnitstate sayfa ilk açılırken bir kez tetiklenir. Daha sonra Build tetiklenir. Sonrasında her setstate yaptığında build tekrar tetiklenir ama initstate tetiklenmez. Şöyle düşün. Sayfa açılırken internetten 20Mb bir veri çekiyosun diyelim çok büyük bir veri. Sonra bunu ekranda gösteriyosun diyelim. Her setstate yaptığında bu 20Mb verinin tekrar tekrar inmesini mi isteriz, yoksa sadece yaptığımız değişikliği mi görmek isteriz?
      Build içinde atama yapmaktan kaçının.

      Field oluştur
      İnitstate içinde değerini ata
      Build içinde göster

      Ayrıca bir diğer sorun getLocation async bir metod. Başında await kullanmalısınız. İnitstate içinde await kullanamazsınız. Dolayısıyla then içinde setstate kullanarak ekranı yenilemelisiniz.

      HseyinAkkaya tamamdır bu şekilde yaptım oldu. Dediğiniz gibi future method ları araştırdığımda mantığını anladım zaten. Çok teşekkür ederim. Hataları göre göre öğreniyoruz 😄

      Write a Reply...