In this guide, we’ll create a simple weather app using Flutter and the OpenWeatherMap API. The app will display the current weather conditions and temperature for a specific city.
Prerequisites
- Basic understanding of Flutter and Dart
- Flutter SDK installed and set up
- An API key for OpenWeatherMap (free tier is sufficient)
Step 1: Create a new Flutter project
First, create a new Flutter project using the following command:
flutter create simple_weather_app
Then, navigate to the project directory:
cd simple_weather_app
Open the project in your favorite code editor.
Step 2: Add necessary dependencies
Add the following dependencies to your pubspec.yaml
file:
dependencies: flutter: sdk: flutter http: ^0.13.3 provider: ^6.0.1 dev_dependencies: flutter_test: sdk: flutter
Then, run flutter packages get
to install the new dependencies.
Step 3: Create a WeatherService class
In the lib
folder, create a new file called weather_service.dart
. This file will contain the code for interacting with the OpenWeatherMap API:
import 'dart:convert'; import 'package:http/http.dart' as http; class WeatherService { final String apiKey; WeatherService({required this.apiKey}); Future<Map<String, dynamic>> fetchWeather(String city) async { final response = await http.get( 'https://api.openweathermap.org/data/2.5/weather?q=$city&appid=$apiKey&units=metric'); if (response.statusCode == 200) { return jsonDecode(response.body); } else { throw Exception('Failed to load weather data'); } } }
This class has a single method, fetchWeather
, which takes a city name as a parameter and returns weather data from the OpenWeatherMap API.
Step 4: Create a WeatherModel class
In the lib
folder, create a new file called weather_model.dart
. This file will define the data model for our weather information:
import 'dart:convert'; import 'package:http/http.dart' as http; class WeatherService { final String apiKey; WeatherService({required this.apiKey}); Future<Map<String, dynamic>> fetchWeather(String city) async { final response = await http.get( 'https://api.openweathermap.org/data/2.5/weather?q=$city&appid=$apiKey&units=metric'); if (response.statusCode == 200) { return jsonDecode(response.body); } else { throw Exception('Failed to load weather data'); } } }
The WeatherModel
class includes a factory constructor that takes a JSON object and creates an instance of the class.
Step 5: Create a WeatherProvider class
In the lib
folder, create a new file called weather_provider.dart
. This file will define the provider for our weather data:
import 'package:flutter/material.dart'; import 'weather_model.dart'; import 'weather_service.dart'; class WeatherProvider with ChangeNotifier { WeatherModel? _weatherData; WeatherService _weatherService; WeatherProvider({required String apiKey}) : _weatherService = WeatherService(apiKey: apiKey); WeatherModel? get weatherData => _weatherData; Future<void> fetchWeather(String city) async { try { final data = await _weatherService.fetchWeather(city); _weatherData = WeatherModel.fromJson(data); notifyListeners(); } catch (e) { print('Error: $e'); } } }
The WeatherProvider
class fetches weather data from the WeatherService
and updates the _weatherData
property when new data is fetched. It also notifies listeners of any changes.
Step 6: Set up the WeatherProvider in the main app
In the lib/main.dart
file, replace the code with the following:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'weather_provider.dart'; import 'weather_screen.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) => WeatherProvider(apiKey: 'YOUR_API_KEY'), child: MaterialApp( title: 'Simple Weather App', theme: ThemeData( primarySwatch: Colors.blue, ), home: WeatherScreen(), ), ); } }
Replace 'YOUR_API_KEY'
with your actual OpenWeatherMap API key. The WeatherProvider
is now set up and can be used throughout the app.
Step 7: Create the WeatherScreen
In the lib
folder, create a new file called weather_screen.dart
. This file will define the main screen of our weather app:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'weather_provider.dart'; class WeatherScreen extends StatelessWidget { final TextEditingController _cityController = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Simple Weather App'), ), body: Padding( padding: EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TextField( controller: _cityController, decoration: InputDecoration( hintText: 'Enter city name', ), ), SizedBox(height: 16.0), ElevatedButton( onPressed: () { Provider.of<WeatherProvider>(context, listen: false) .fetchWeather(_cityController.text); }, child: Text('Get Weather'), ), SizedBox(height: 32.0), Consumer<WeatherProvider>( builder: (context, weatherProvider, child) { final weatherData = weatherProvider.weatherData; if (weatherData == null) { return Text('No weather data available'); } else { return Column( children: [ Text( weatherData.cityName, style: TextStyle(fontSize: 24.0), ), Text( '${weatherData.temperature.toStringAsFixed(1)}°C', style: TextStyle(fontSize: 48.0), ), Text( weatherData.description, style: TextStyle(fontSize: 18.0), ), ], ); } }, ), ], ), ), ); } }
This screen displays a TextField for the user to enter a city name, a button to fetch the weather data, and a Consumer
to display the current weather data.
Now you can run the app using the following command:
flutter run
You should see the simple weather app displaying a TextField and a button. Enter a city name, tap ‘Get Weather,’ and the app will fetch and display the current weather conditions and temperature for the specified city.
This is just a basic example of creating a weather app in Flutter. You can expand on this concept by adding more features, like displaying a weather forecast or handling errors more gracefully.