0

I'm developing a weather app using an API from OpenWeatherMap. Every time I try to run my code, the error late initialization pops up. I've tried adding the null safety check(!) in place of late but it's still the same. Any idea where I could have gone wrong? Any help would be deeply appreciated. A sample code for solving the error would help a lot. Thanks!!

The error I'm getting in the console:

Performing hot restart... 1,492ms Restarted application in 1,501ms. ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ The following LateError was thrown building: LateInitializationError: Field 'weatherInfo' has not been initialized.

When the exception was thrown, this was the stack: C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart 251:49 throw packages/finalproject/LastProject/LastProject_Screen.dart 13:44 get weatherInfo packages/finalproject/LastProject/LastProject_Screen.dart 10:56 mainBodyWidget
packages/finalproject/LastProject/LastProject_Screen.dart 10:56 packages/flutter/src/widgets/sliver.dart 456:22 build packages/flutter/src/widgets/sliver.dart 1214:28 [_build]
packages/flutter/src/widgets/sliver.dart 1227:55 packages/flutter/src/widgets/framework.dart 2573:19 buildScope
packages/flutter/src/widgets/sliver.dart 1220:5 createChild
packages/flutter/src/rendering/sliver_multi_box_adaptor.dart 349:23 packages/flutter/src/scheduler/binding.dart 1080:9 handleDrawFrame packages/flutter/src/scheduler/binding.dart 863:7 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19 internalCallback

Note: This is just a part of the errors in the console because there are many.

The Code for UI:

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';

import 'LastProject_model.dart';

class LastProjectScreen extends StatefulWidget {
  const LastProjectScreen({Key? key}) : super(key: key);

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

class _LastProjectScreenState extends State<LastProjectScreen> {

  //initializing model class object
  late WeatherInfo weatherInfo;
  TextEditingController _textEditingController = TextEditingController();

  //overriding initstate to parse the data and display it on the screen
  @override
  void initState() {
    super.initState();
  }


//data parsing function to call the data from the json file
  getData() async {
    http.Response jsondata = await http.get(Uri.parse(
        'https://api.openweathermap.org/data/2.5/forecast/daily?q=${_textEditingController.text}&units=metric&cnt=7&appid=3c044b7295d2df14f8bee74c19d4b96f'));
    print(jsondata.body);
    weatherInfo = WeatherInfo.fromJson(json.decode(jsondata.body));
    return weatherInfo;
  }


//first row of the screen
  Widget uirow1(WeatherInfo weatherInfo) {
    return Container(
      padding: EdgeInsets.all(5),
      margin: EdgeInsets.only(left: 20, right: 20, top: 20),
      decoration: BoxDecoration(
          // color: Colors.white,
          gradient: LinearGradient(
              colors: [Colors.blue.shade200, Colors.blue.shade50]),
          borderRadius: BorderRadius.all(Radius.circular(20)),
          boxShadow: [
            BoxShadow(
              color: Colors.grey.withOpacity(0.1),
              spreadRadius: 5,
              blurRadius: 7,
              offset: Offset(0, 3),
            )
          ]),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              Text(
                'name',
                // weatherInfo.city.name,
                style: TextStyle(fontSize: 17, fontWeight: FontWeight.w700),
              ),
              SizedBox(height: 5),
              Text('temp °F',
                  style: TextStyle(
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                      color: Colors.black)),
              SizedBox(height: 5),
              Text('description',
                  style: TextStyle(
                      fontSize: 15,
                      fontWeight: FontWeight.bold,
                      color: Colors.black))
            ],
          ),
          Icon(
            Icons.cloud,
            color: Colors.pink[400],
            size: 100,
          ),
        ],
      ),
    );
  }


//second row of the screen
  Widget uirow2() {
    return Container(
      padding: EdgeInsets.all(5),
      margin: EdgeInsets.all(20),
      decoration: BoxDecoration(
          // color: Colors.white,
          gradient: LinearGradient(
              colors: [Colors.blue.shade200, Colors.blue.shade50]),
          borderRadius: BorderRadius.all(Radius.circular(20)),
          boxShadow: [
            BoxShadow(
              color: Colors.grey.withOpacity(0.1),
              spreadRadius: 5,
              blurRadius: 7,
              offset: Offset(0, 3),
            )
          ]),
      child: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Text('windSpeed',
                  style: TextStyle(
                    fontSize: 15,
                  )),
              // SizedBox(width: 3),
              Text('humidity',
                  style: TextStyle(
                    fontSize: 15,
                  )),
              // SizedBox(width: 5),
              Text('°F',
                  style: TextStyle(
                    fontSize: 15,
                  )),
            ],
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Icon(Icons.air_outlined, color: Colors.grey[600], size: 25),
              // const SizedBox(width: 5),
              Icon(Icons.whatshot_rounded, color: Colors.grey[600], size: 25),
              // const SizedBox(width: 5),
              Icon(Icons.air_outlined, color: Colors.grey[600], size: 25)
            ],
          ),
        ],
      ),
    );
  }


//main body widget of the screen
  Widget mainBodyWidget(BuildContext context) {
    return
        // ListView(scrollDirection: Axis.vertical, children: [
        Container(
      padding: EdgeInsets.all(15),
      decoration: const BoxDecoration(
          image: DecorationImage(
              image: NetworkImage(
                  'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSZCv1LyQUyAJQE21-uNUMx3S8ZgK2U9S--1wQB59QaTFHBp2VqxGTAen5FRA7m5h-E4OU&usqp=CAU'),
              fit: BoxFit.fill)),
      child: Column(
        children: [
          searchwidget(),
          const SizedBox(height: 15),
          uirow1(weatherInfo),
          const SizedBox(height: 15),
          uirow2(),
          const SizedBox(height: 15),
          uirow3()
        ],
      ),
    );
  }


//third row of the screen
  Widget uirow3() {
    return Container(
        padding: EdgeInsets.all(15),
        margin: EdgeInsets.only(left: 20, right: 20),
        height: 180,
        decoration: BoxDecoration(
            gradient: LinearGradient(
                colors: [Colors.blue.shade200, Colors.blue.shade50]),
            borderRadius: BorderRadius.all(Radius.circular(20)),
            boxShadow: [
              BoxShadow(
                color: Colors.grey.withOpacity(0.1),
                spreadRadius: 5,
                blurRadius: 7,
                offset: Offset(0, 3),
              )
            ]),
        child: ListView.separated(
            scrollDirection: Axis.horizontal,
            itemBuilder: (BuildContext context, int index) {
              return Container(
                child: uirow3data(),
              );
            },
            separatorBuilder: (BuildContext context, int index) {
              return SizedBox(width: 20);
            },
            itemCount: 7
            // weatherInfo.weatherListInfo.length,
            ));
  }

//data for the third row of the screen
  Widget uirow3data() {
    return Column(
      children: [
        Center(
            child: Text('Saturday',
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                ))),
        SizedBox(height: 5),
        Icon(
          Icons.cloud,
          color: Colors.pink[400],
          size: 50,
        ),
        SizedBox(height: 4),
        Text('High: 71°F'),
        SizedBox(height: 3),
        Text('Low: 71°F'),
        SizedBox(height: 3),
        Text('Hum: 40%'),
        SizedBox(height: 3),
        Text('Win: 4 mi/h')
      ],
    );
  }

//search textfiled widget
  Widget searchwidget() {
    return Container(
      margin: EdgeInsets.only(left: 20, right: 20, top: 10),
      child: Center(
        child: TextField(
          controller: _textEditingController,
          decoration: InputDecoration(
              enabledBorder: OutlineInputBorder(
                  gapPadding: 3.0,
                  borderSide: const BorderSide(color: Colors.grey, width: 2.0),
                  borderRadius: BorderRadius.circular(11)),
              hintText: 'Search',
              hintStyle: const TextStyle(color: Colors.grey),
              prefixIcon: const Icon(
                Icons.search_sharp,
                color: Colors.grey,
              ),
              suffixIcon: InkWell(
                child: const Icon(Icons.navigate_next, color: Colors.grey),
                onTap: () => getData(),
              )),
        ),
      ),
    );
  }

//main container widget
  Widget mainContainerWidget(BuildContext context) {
    return Scaffold(
        body: FutureBuilder(
                future: getData(),
                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    return Center(child: Text("Couldn't load the data"));
                  }
                  if (snapshot.hasData) {
                    return Text("Data is being processed");
                  }
                  if (snapshot.data == null) {
                    return ListView.builder(
                        scrollDirection: Axis.vertical,
                        itemCount: 1,
                        shrinkWrap: true,
                        itemBuilder: (context, index) {
                          return Column(
                            children: [mainBodyWidget(context)],
                          );
                        });
                  }
                  return CircularProgressIndicator();
                }));
  }

//Main build function
  @override
  Widget build(BuildContext context) {
    return mainContainerWidget(context);
  }
}

The Code for Model class:

class WeatherInfo {
  late CityInfo city;
  late String cod;
  late double message;
  late int cnt;
  late List<WeatherListInfo> weatherListInfo;

  WeatherInfo(
      this.city, this.cod, this.message, this.cnt, this.weatherListInfo);

  factory WeatherInfo.fromJson(Map<String, dynamic> json) {
    return WeatherInfo(
        CityInfo.fromJson(json["city"]),
        json["cod"],
        json["message"],
        json["cnt"],
        (json["list"] as List).map((e) => WeatherListInfo.fromJson(e)).toList());
  }
}

class CityInfo {
  late String id;
  late String name;
  late String country;
  late String population;
  late String timezone;

  CityInfo(this.id, this.name, this.country, this.population, this.timezone);

  factory CityInfo.fromJson(Map<String, dynamic> json) {
    return CityInfo(json["id"].toString(), json["name"], json["country"],
        json["population"].toString(), json["timezone"].toString());
  }
}

class WeatherListInfo {
  late String dt;
  late String sunrise;
  late String sunset;
  late TemperatureListInfo temperatureListInfo;
  late String pressure;
  late String humidity;
  late List<WeatherDetailInfo> weatherDetailInfo;
  late FeelsLikeListInfo feelsLikeInfo;
  late String speed;
  late String deg;
  late String gust;
  late String clouds;
  late String pop;
  late String rain;

  WeatherListInfo(
    this.dt,
    this.sunrise,
    this.sunset,
    this.temperatureListInfo,
    this.pressure,
    this.humidity,
    this.weatherDetailInfo,
    this.feelsLikeInfo,
    this.speed,
    this.deg,
    this.gust,
    this.clouds,
    this.pop,
    this.rain,
  );

  factory WeatherListInfo.fromJson(Map<String, dynamic> json) {
    return WeatherListInfo(
      json["dt"].toString(),
      json["sunrise"].toString(),
      json["sunset"].toString(),
      TemperatureListInfo.fromJson(json["temp"]),
      json["pressure"].toString(),
      json["humidity"].toString(),
      (json["weather"] as List).map((e) => WeatherDetailInfo.fromJson(e)).toList(),
      FeelsLikeListInfo.fromJson(json["feels_like"]),
      json["speed"].toString(),
      json["deg"].toString(),
      json["gust"].toString(),
      json["clouds"].toString(),
      json["pop"].toString(),
      json["rain"].toString(),
    );
  }
}

class TemperatureListInfo {
  late String day;
  late String min;
  late String max;
  late String night;
  late String eve;
  late String morn;

  TemperatureListInfo(
      this.day, this.night, this.eve, this.morn, this.min, this.max);

  factory TemperatureListInfo.fromJson(Map<String, dynamic> json) {
    return TemperatureListInfo(
      json["day"].toString(),
      json["night"].toString(),
      json["eve"].toString(),
      json["morn"].toString(),
      json["min"].toString(),
      json["max"].toString(),
    );
  }
}

class FeelsLikeListInfo {
  late String day;
  late String night;
  late String eve;
  late String morn;

  FeelsLikeListInfo(this.day, this.night, this.eve, this.morn);

  factory FeelsLikeListInfo.fromJson(Map<String, dynamic> json) {
    return FeelsLikeListInfo(
      json["day"].toString(),
      json["night"].toString(),
      json["eve"].toString(),
      json["morn"].toString(),
    );
  }
}

class WeatherDetailInfo {
  late String id;
  late String main;
  late String description;
  late String icon;

  WeatherDetailInfo(this.id, this.main, this.description, this.icon);

  factory WeatherDetailInfo.fromJson(Map<String, dynamic> json) {
    return WeatherDetailInfo(
      json["id"].toString(),
      json["main"],
      json["description"],
      json["icon"],
    );
  }
}
Poojitha
  • 1
  • 2

1 Answers1

0

The error message says it, you didn't initialize weatherInfo. When you mark a variable as late you must initialize it later, but in your case, you only initialize it when you call getData(), so ui complains because it uses a variable that is not yet initialized. You have to options here,

first: you call getData in initState, so the variable will be initialized.

or, second: you remove the late keyword and make the object nullable, but now you'll have to add null checks all over the code.

Michael Soliman
  • 2,240
  • 3
  • 7
  • 20
  • I tried both methods but it's still the same. – Poojitha Nov 13 '21 at 14:14
  • yeah i guessed that the first method might not work, probably because the ui can be built before the variable is initialized, as you don't use async before the function. did you try removing the `late` keyword ? if you did and that didn't work, it was because of some other problem, check the error message when you do that – Michael Soliman Nov 13 '21 at 18:49