skip to Main Content

I’m trying to pass data to a flutter user interface from the open weather API. I think it has something to do with where I am initializing the city name variable as it gets rebuilt every time I refresh the app and just loads the original string instead of the city I put in the text field. How would I fix this code so I can pull the information from the API using the new city name.

import 'package:flutter/material.dart';
import 'package:weather_solo/logic/get_weather.dart';
//import 'logic/additional_information_info.dart';
import 'logic/weather_forecast_time.dart';

class WeatherHomePage extends StatefulWidget {
  const WeatherHomePage({super.key});

  @override
  State<WeatherHomePage> createState() => _WeatherHomePageState();
}

class _WeatherHomePageState extends State<WeatherHomePage> {
  TextEditingController cityNameController = TextEditingController();
  GetWeather getWeather = GetWeather();
  String cityName = 'Hamilton';
  late Future<Map<String, dynamic>> weather = getWeather.getCurrentWeather(cityName);
  // late int iconID = weather['list'][0];
  //list[0].weather[0].id
  

  @override
  void initState() {
    super.initState();
    weather = getWeather.getCurrentWeather(cityName);
  }


  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: const Text('My Weather App',
          style: TextStyle(
            fontSize: 20,
          ),),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Card(
                elevation: 10,
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Column(
                    children: [
                      TextField(
                        controller: cityNameController,
                        decoration: const InputDecoration(
                          hintText: 'Please Enter City Name Here',
                          border: OutlineInputBorder()
                        ),
                      ),
                      ElevatedButton(onPressed: () {
                        setState(() {
                          cityName = cityNameController.text;
                          cityNameController.clear();
                         getWeather.getCurrentWeather(cityName);
                        });
                                
                      },
                      style: const ButtonStyle(
                        elevation: MaterialStatePropertyAll(10),
                        backgroundColor:
                          MaterialStatePropertyAll(Colors.red),
                        foregroundColor: MaterialStatePropertyAll(Colors.black),
                          ),
                      child: const Text(
                        'Choose City'
                      ),
                      
                      ),
                    ],
                  ),
                ),
              ),
              // Flex for weather data, needs to be wrapped in a FutureBuilder as this is the section that will update
             FutureBuilder(
                future: weather,
                builder: (context, snapshot) {
                  if(snapshot.connectionState == ConnectionState.waiting) {
                    return const Center(
                      child: CircularProgressIndicator.adaptive(),
                    );
                  }

                  if (snapshot.hasError) {
                    return Center(
                      child: Text(snapshot.error.toString()),
                    );
                  }
                

                  final data = snapshot.data!;
                  final currentWeatherData = data['list'][0];

                  final currentIcon = currentWeatherData['weather'][0]['id'];

                 return Expanded(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: [
                      Card(
                        elevation: 10, //Main weather data card
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.spaceAround,
                          children: [
                            const SizedBox(width: double.infinity,),
                            Text(cityName,
                            style: const TextStyle(
                              fontSize: 15,
                            ),),
                            const SizedBox(height: 10,),
                            Text('Weather icon code $currentIcon Rain',
                            style: const TextStyle(
                              fontSize: 10
                            ),),
                            const SizedBox(
                              height: 5,
                            ),
                            const Icon(Icons.cloud,
                            size: 20,),
                            const SizedBox(height: 5,),
                            const Text('27 °C',
                            style: TextStyle(
                              fontSize: 20
                            ),) //Hold down left alt and numpad 0176 for degree symbol
                          ],
                        ),
                    ),
                    // Wetaher data time forecast
                    SizedBox(
                      height: 100,
                      child: ListView.builder(itemCount: 5,scrollDirection: Axis.horizontal,itemBuilder: (context ,index) {
                        return const WeatherForecastTime(time: '09.00', icon: Icons.sunny, desctription: 'Sunny',);
                      },
                      ),
                      ),
                      //Additional information
                      // const Row(
                      //   mainAxisAlignment: MainAxisAlignment.spaceAround,
                      //   children: [
                      //     AdditionalInformationInfo(title: 'Humidity', icon: Icons.water_drop, stats: '4757',),
                      //     AdditionalInformationInfo(title: 'Wind Speed', icon: Icons.air, stats: 'Fast',),
                      //     AdditionalInformationInfo(title: 'Pressure', icon: Icons.umbrella, stats: '775',)
                      //   ],
                      // ),
                    ],
                  ),
                );
                }
              )
            ],
          ),
        ),
      ),
    );
  }
}




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

class GetWeather {

  Future<Map<String, dynamic>> getCurrentWeather(String cityName) async {
    try {
      final result = await http.get(Uri.parse(
          'http://api.openweathermap.org/data/2.5/forecast?q=$cityName&appid=$openWeatherAPIKey'));
      final data = jsonDecode(result.body);

      if (result.statusCode != 200) {
        throw 'An unexpected error occured ${data['cod']}';
      }
      print(result.body);
      return data;
    } catch (e) {
      throw e.toString();
    }
  }

  Icon getWeatherIcon(int condition) {
    switch (condition) {
      case < 300:
      return const Icon(Icons.thunderstorm);
      case < 400:
      return const Icon(Icons.water_drop);
      case < 600:
      return const Icon(Icons.umbrella);
      case < 700:
      return const Icon(Icons.snowing);
      case < 800:
      return const Icon(Icons.foggy);
      case == 800:
      return const Icon(Icons.sunny);
      case <= 804:
      return const Icon(Icons.cloud);
      default:
      return const Icon(Icons.question_mark);
    } 
  }

}

2

Answers


  1. Chosen as BEST ANSWER

    This fixed it.

     ElevatedButton(onPressed: () {
                        setState(() {
                          cityName = cityNameController.text;
                          cityNameController.clear();
                          weather = getWeather.getCurrentWeather(cityName);
                        });
                                
                      },
    

  2. The issue you’re encountering is due to the location where you initialize the cityName variable. As you mentioned, it’s initialized at the class level, which causes it to retain its original value throughout the widget’s life cycle, even after updating the text field. To fix this and ensure that the updated city name is used to fetch weather data, you should move the API call to getCurrentWeather inside the onPressed method of the ElevatedButton.

    ElevatedButton(
           onPressed: () {
             setState(() {
             final cityName = cityNameController.text;
                 cityNameController.clear();
                 weather = getWeather.getCurrentWeather(cityName);
           });
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search