1

I'm making weather forecast app with api. It has search bar on top and for now it looks like this: ui

It works but I'm getting this exception exception

and sometimes this error: error

main.dart

  WeatherAPI client = WeatherAPI();
  Weather? data = Weather();
  String city = "Paris";

  void getData() async {
    final response = await client.getCurrentWeather(city);
    
    setState(() {
      data = response;
    });
  }

    @override
  Widget build(BuildContext context) {

    getData();

    return MaterialApp(
      theme: ThemeData(fontFamily: 'Poppins'),
      debugShowCheckedModeBanner: false,
      home: Container (
        decoration: BoxDecoration(
          gradient: LinearGradient(begin: Alignment.topRight, end: Alignment.bottomLeft, 
          colors: [Color.fromRGBO(61, 43, 65, 1.0), Color.fromRGBO(39, 35, 52, 1.0)])
        ),
        child: Scaffold(
          resizeToAvoidBottomInset: false,
          backgroundColor: Colors.transparent,
          appBar: AppBar(
            title: title,
            elevation: 0,
            backgroundColor: Colors.transparent,
            actions: [
              IconButton(onPressed: (){
                setState(() {
                  if(this.searchIcon.icon == Icons.search){
                    this.searchIcon = Icon(Icons.cancel);
                    this.title = TextField(
                      style: TextStyle(color: LIGHT_TEXT, fontSize: 15),
                      decoration: InputDecoration(border: InputBorder.none, hintText: "Search location",hintStyle: TextStyle(color: Colors.white30)),
                      textInputAction: TextInputAction.go,
                      controller: searchValue,
                      onSubmitted: (value) {
                        city = value;
                        this.title = Text("Weather Forecast");
                        this.searchIcon = Icon(Icons.search);
                        this.searchValue.text = "";
                      },
                    );
                  } else {
                    this.searchIcon = Icon(Icons.search);
                    this.title = Text("Weather Forecast");
                  }
                });
              }, icon: searchIcon,
          )],
          ),
          

          body: Column( 
            children: [ 
              if(data != null)
                Container(  
                  height: 40,
                ),
                currentWeather("${data!.city}", "${data!.temp}", "${data!.region}", "${data!.date}", "${data!.imgUrl}"),
                Container(
                  height: 80,
                  child: Divider(color: LIGHT_TEXT_2, indent: 40, endIndent: 40,)
                ),
                additionalWeather("${data!.feelsLike}", "${data!.wind}", "${data!.humidity}"),
                  
            ])
        
         )   
     )
     );
    
  }

Weather model:

class Weather {
  String? city;
  String? region;
  double? temp;
  double? wind;
  int? humidity;
  double? feelsLike;
  double? gust;
  String? date;
  int? isDay;
  String? imgUrl;

  Weather({this.city, this.region, this.temp, this.wind, this.feelsLike, this.gust, this.humidity, this.date, this.isDay, this.imgUrl});

  Weather.fromJSON(Map<String, dynamic> json){
    city = json['location']['name'];
    region = json['location']['region'];
    temp = json['current']['temp_c'];
    wind = json['current']['wind_kph'];
    humidity = json['current']['humidity'];
    feelsLike = json['current']['feelslike_c'];
    gust = json['current']['gust_kph'];
    date = json['location']['localtime'];
    date = date!.substring(11);
    isDay = json['current']['is_day'];
    imgUrl = json['current']['condition']['icon'];
  }


}

Weather api:


class WeatherAPI {

  Future<Weather> getCurrentWeather(String? city) async {
    var url = Uri.parse("http://api.weatherapi.com/v1/current.json?key=&q=$city&aqi=no");
    
    var response = await http.get(url);
    //print(response.statusCode);
    var body = jsonDecode(response.body);
    return Weather.fromJSON(body);
  }

}

This is my code simplified. First I made this with Future builder but that way I failed to update the page when i search for another city. After that I managed to make the application work, but I can't fix this error. The first exception does not appear if I call getdata() in initstate() but in that case I am not able to search for the other city. Maybe this is not the right way to do this, I'm new to flutter. Any advice is welcome.

4
  • The exception mentions the NetworkImage widget but that doesn't exist in your code snippets. Just guessing but I image that imgUrl is null in your model and you are creating a string using this value which is causing the error.
    – Schleis
    Commented Mar 6, 2023 at 16:36
  • @Schleis the image (icon) is displayed after half a second or a second. but i think it throws me this error before that time, looks like scaffold is not waiting for API. imgUrl is converted in this currentWeather class (I didn't paste it here) and it looks like: Image.network("https:$imgUrl")
    – aNavi
    Commented Mar 6, 2023 at 16:43
  • Do you have any null check when you are creating the image? The text of the exception says that the the NetworkImage is looking for a URL of https:null. So you might want to wrap the creating of the image with a null check to make sure that you have a url to get
    – Schleis
    Commented Mar 6, 2023 at 16:51
  • @Schleis I tried to add if(imgUrl != null) but it doesnt work. it looks like this linkpicture.com/q/imgurl.jpg
    – aNavi
    Commented Mar 6, 2023 at 17:03

1 Answer 1

0

Looks like the most important part of code is missing, but I guess image rendering takes place in currentWeather widget/method.

After analyzing your code I can see that you are building your widget even if you don't have data yet. It may be a root of many problem, it is usually good practice to render some spinner/loading widget during data loading.

You can may take a look at this tutorial: https://www.youtube.com/watch?v=nLlVANBmFJM.

Going back to NetworkImage, for debugging purposes you can handle some errors this way:

Image.network('<some_url>',
    errorBuilder: (BuildContext context, Object exception, StackTrace stackTrace) {
        return Text('Some replacement for invalid image.');
    },
),

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.