How to pass data from an API to flutter UI

97 views Asked by At

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);
    } 
  }

}
1

There are 1 answers

0
The Synergist On

This fixed it.

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