Building a Weather App with Flutter: API Integration and UI Design
Weather apps have become an integral part of our daily lives, helping us plan our activities and stay prepared for the elements. If you’re an aspiring mobile app developer looking to enhance your skills with Flutter, building a weather app is an excellent project to undertake. In this tutorial, we’ll guide you through the process of creating a weather app with Flutter, complete with API integration for real-time weather data and a beautifully designed user interface.
Table of Contents
1. Prerequisites
Before we dive into the development process, make sure you have the following prerequisites in place:
1.1. Flutter Installed
Ensure that you have Flutter and Dart installed on your system. You can follow the official Flutter installation guide for your specific operating system: Flutter Installation Guide.
1.2. OpenWeatherMap API Key
To fetch weather data, you’ll need an API key from OpenWeatherMap. You can sign up for a free API key at OpenWeatherMap.
1.3. Basic Flutter Knowledge
Familiarity with the basics of Flutter, such as widgets, state management, and navigation, will be helpful.
Now that you have all the prerequisites covered, let’s get started on building your weather app.
Step 1: Project Setup
Begin by creating a new Flutter project using the following command:
bash flutter create weather_app cd weather_app
Replace weather_app with your preferred project name.
Step 2: Dependencies
In your pubspec.yaml file, add the necessary dependencies for this project:
yaml dependencies: flutter: sdk: flutter http: ^0.13.3 # For making HTTP requests provider: ^5.0.3 # For state management flutter_svg: ^0.24.0 # For SVG support
Save the file, and run flutter pub get to fetch the packages.
Step 3: Create Models
Create two Dart files, weather_data.dart and location_data.dart, to define the data models for weather information and location details, respectively.
dart // weather_data.dart class WeatherData { final String city; final String description; final double temperature; final int humidity; final String iconCode; WeatherData({ required this.city, required this.description, required this.temperature, required this.humidity, required this.iconCode, }); } // location_data.dart class LocationData { final double latitude; final double longitude; LocationData({ required this.latitude, required this.longitude, }); }
Step 4: API Integration
We’ll use the http package to make API requests to OpenWeatherMap. Create a weather_api.dart file to handle the API calls:
dart import 'dart:convert'; import 'package:http/http.dart' as http; class WeatherApi { final String apiKey; final String apiUrl = 'https://api.openweathermap.org/data/2.5/weather'; WeatherApi({required this.apiKey}); Future<Map<String, dynamic>> fetchWeatherData(double latitude, double longitude) async { final response = await http.get('$apiUrl?lat=$latitude&lon=$longitude&appid=$apiKey&units=metric'); if (response.statusCode == 200) { return json.decode(response.body); } else { throw Exception('Failed to load weather data'); } } }
Make sure to replace ‘YOUR_API_KEY’ with your actual OpenWeatherMap API key.
Step 5: Implement State Management
For state management, we’ll use the provider package. Create a weather_provider.dart file to manage the weather data.
dart import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:your_project_name/location_data.dart'; import 'package:your_project_name/weather_data.dart'; import 'package:your_project_name/weather_api.dart'; class WeatherProvider with ChangeNotifier { WeatherData? _weatherData; LocationData? _locationData; WeatherProvider() { _locationData = LocationData(latitude: 0.0, longitude: 0.0); // Initialize with default location fetchWeatherData(); } WeatherData? get weatherData => _weatherData; LocationData? get locationData => _locationData; void setLocation(double latitude, double longitude) { _locationData = LocationData(latitude: latitude, longitude: longitude); fetchWeatherData(); } Future<void> fetchWeatherData() async { try { final api = WeatherApi(apiKey: 'YOUR_API_KEY'); final data = await api.fetchWeatherData(_locationData!.latitude, _locationData!.longitude); _weatherData = WeatherData( city: data['name'], description: data['weather'][0]['description'], temperature: data['main']['temp'], humidity: data['main']['humidity'], iconCode: data['weather'][0]['icon'], ); notifyListeners(); } catch (e) { print('Error fetching weather data: $e'); } } }
Replace ‘YOUR_API_KEY’ with your actual OpenWeatherMap API key.
Step 6: UI Design
Now, let’s create the user interface for your weather app. We’ll design a simple yet attractive interface using Flutter’s widgets and the flutter_svg package for displaying weather icons.
Home Screen
Create a home_screen.dart file for the home screen of your weather app:
dart import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; import 'package:your_project_name/weather_data.dart'; import 'package:your_project_name/weather_provider.dart'; class HomeScreen extends StatelessWidget { @override Widget build(BuildContext context) { final weatherData = Provider.of<WeatherProvider>(context).weatherData; return Scaffold( appBar: AppBar( title: Text('Weather App'), ), body: Center( child: weatherData != null ? WeatherInfoWidget(weatherData: weatherData) : CircularProgressIndicator(), ), floatingActionButton: FloatingActionButton( onPressed: () { // Open a location picker screen or use device location services }, child: Icon(Icons.location_on), ), ); } } class WeatherInfoWidget extends StatelessWidget { final WeatherData weatherData; WeatherInfoWidget({required this.weatherData}); @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SvgPicture.asset('assets/weather_icons/${weatherData.iconCode}.svg', width: 100), SizedBox(height: 16), Text(weatherData.city, style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), Text(weatherData.description, style: TextStyle(fontSize: 16)), SizedBox(height: 16), Text('${weatherData.temperature.toStringAsFixed(1)}°C', style: TextStyle(fontSize: 32)), Text('Humidity: ${weatherData.humidity}%', style: TextStyle(fontSize: 16)), ], ); } }
In this code, we use the SvgPicture.asset widget to display weather icons. Make sure you have weather icons in SVG format in an assets/weather_icons folder.
Location Picker Screen
Create a location_picker_screen.dart file for the location picker screen, where users can choose a location or use device location services:
dart import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:your_project_name/location_data.dart'; import 'package:your_project_name/weather_provider.dart'; class LocationPickerScreen extends StatefulWidget { @override _LocationPickerScreenState createState() => _LocationPickerScreenState(); } class _LocationPickerScreenState extends State<LocationPickerScreen> { double _latitude = 0.0; double _longitude = 0.0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Choose Location'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Latitude: $_latitude'), Text('Longitude: $_longitude'), ElevatedButton( onPressed: () { // Implement location picker logic here // Update _latitude and _longitude accordingly final weatherProvider = Provider.of<WeatherProvider>(context, listen: false); weatherProvider.setLocation(_latitude, _longitude); Navigator.pop(context); }, child: Text('Set Location'), ), ], ), ), ); } }
This screen allows users to set a custom location by providing latitude and longitude coordinates.
Step 7: Navigation
Configure navigation within your app by creating a routes.dart file:
dart import 'package:flutter/material.dart'; import 'package:your_project_name/home_screen.dart'; import 'package:your_project_name/location_picker_screen.dart'; final Map<String, WidgetBuilder> routes = { '/': (context) => HomeScreen(), '/location_picker': (context) => LocationPickerScreen(), };
Step 8: Main Function
Update the main.dart file to include the necessary configurations and start the app:
dart import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:your_project_name/routes.dart'; import 'package:your_project_name/weather_provider.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) => WeatherProvider(), child: MaterialApp( title: 'Weather App', theme: ThemeData(primarySwatch: Colors.blue), initialRoute: '/', routes: routes, ), ); } }
Step 9: Running the App
You can now run your weather app using the following command:
bash flutter run
Open the app on your emulator or physical device, and you’ll see your beautiful weather app in action. You can navigate to the location picker screen by tapping the floating action button and set a custom location.
Congratulations! You’ve successfully built a weather app with Flutter that integrates real-time weather data and boasts an attractive user interface.
Conclusion
In this tutorial, we walked through the process of building a weather app with Flutter, focusing on API integration and UI design. You’ve learned how to set up your project, fetch weather data from OpenWeatherMap, manage app state using the provider package, and create a user-friendly interface. This project not only enhances your Flutter skills but also gives you a real-world application to showcase in your portfolio. Happy coding!
Table of Contents