Published on August 12, 2024By DeveloperBreeze

Building an Advanced Weather App with Flutter and Dart

Prerequisites

Before we start, ensure that your Flutter environment is set up. You should have Flutter and Dart installed, along with an IDE like Android Studio or Visual Studio Code.

Overview

Our weather app will:

  • Fetch weather data from an external API.

  • Display current temperature, weather conditions, and an icon representing the weather.

  • Implement navigation between different screens.

Step 1: Setting Up the Project

Create a new Flutter project:

flutter create weather_app

Navigate to the project directory:

cd weather_app

Open the project in your preferred IDE.

Step 2: Add Dependencies

We’ll use the http package to make network requests and provider for state management. Update your pubspec.yaml file to include these dependencies:

dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.3
  provider: ^6.0.0

Run flutter pub get to install the packages.

Step 3: Create the UI

Let's start by building the UI components.

Create a WeatherScreen Widget

Create a new file lib/screens/weather_screen.dart and add the following code:

import 'package:flutter/material.dart';

class WeatherScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Weather App'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'City Name',
              style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 16),
            Text(
              '25°C',
              style: TextStyle(fontSize: 56),
            ),
            SizedBox(height: 16),
            Icon(
              Icons.wb_sunny,
              size: 100,
            ),
            SizedBox(height: 16),
            Text(
              'Clear Sky',
              style: TextStyle(fontSize: 24),
            ),
          ],
        ),
      ),
    );
  }
}

Update main.dart

Modify lib/main.dart to load WeatherScreen:

import 'package:flutter/material.dart';
import 'screens/weather_screen.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Weather App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: WeatherScreen(),
    );
  }
}

Step 4: Integrate Weather API

We will use the [OpenWeatherMap API](https://openweathermap.org/api) to fetch weather data. You’ll need to sign up and get an API key.

Create a Weather Model

Create a new file lib/models/weather.dart and define the data model:

class Weather {
  final String cityName;
  final double temperature;
  final String description;
  final String icon;

  Weather({
    required this.cityName,
    required this.temperature,
    required this.description,
    required this.icon,
  });

  factory Weather.fromJson(Map<String, dynamic> json) {
    return Weather(
      cityName: json['name'],
      temperature: json['main']['temp'].toDouble(),
      description: json['weather'][0]['description'],
      icon: json['weather'][0]['icon'],
    );
  }
}

Fetch Weather Data

Create a new file lib/services/weather_service.dart to handle API requests:

import 'dart:convert';
import 'package:http/http.dart' as http;
import '../models/weather.dart';

class WeatherService {
  final String apiKey = 'YOUR_API_KEY';
  final String baseUrl = 'https://api.openweathermap.org/data/2.5/weather';

  Future<Weather> fetchWeather(String city) async {
    final response = await http.get(Uri.parse('$baseUrl?q=$city&appid=$apiKey&units=metric'));

    if (response.statusCode == 200) {
      return Weather.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to load weather data');
    }
  }
}

Step 5: Implement State Management

We will use the provider package to manage the app's state.

Create a Weather Provider

Create a new file lib/providers/weather_provider.dart:

import 'package:flutter/material.dart';
import '../models/weather.dart';
import '../services/weather_service.dart';

class WeatherProvider with ChangeNotifier {
  final WeatherService _weatherService = WeatherService();
  Weather? _weather;

  Weather? get weather => _weather;

  Future<void> fetchWeather(String city) async {
    _weather = await _weatherService.fetchWeather(city);
    notifyListeners();
  }
}

Update main.dart

Wrap the WeatherScreen with ChangeNotifierProvider:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'screens/weather_screen.dart';
import 'providers/weather_provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => WeatherProvider(),
      child: MaterialApp(
        title: 'Flutter Weather App',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: WeatherScreen(),
      ),
    );
  }
}

Step 6: Connect UI with State

Update the WeatherScreen to display real data.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/weather_provider.dart';

class WeatherScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final weatherProvider = Provider.of<WeatherProvider>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Weather App'),
      ),
      body: Center(
        child: weatherProvider.weather == null
            ? Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    'Enter City Name',
                    style: TextStyle(fontSize: 24),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: TextField(
                      onSubmitted: (value) {
                        weatherProvider.fetchWeather(value);
                      },
                      decoration: InputDecoration(
                        border: OutlineInputBorder(),
                        labelText: 'City',
                      ),
                    ),
                  ),
                ],
              )
            : Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    weatherProvider.weather!.cityName,
                    style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
                  ),
                  SizedBox(height: 16),
                  Text(
                    '${weatherProvider.weather!.temperature}°C',
                    style: TextStyle(fontSize: 56),
                  ),
                  SizedBox(height: 16),
                  Image.network(
                    'http://openweathermap.org/img/wn/${weatherProvider.weather!.icon}@2x.png',
                  ),
                  SizedBox(height: 16),
                  Text(
                    weatherProvider.weather!.description,
                    style: TextStyle(fontSize: 24),
                  ),
                ],
              ),
      ),
    );
  }
}

Step 7: Testing the App

Run the app using:

flutter run

Test the app by entering different city names and observing the weather data displayed.

Conclusion

In this tutorial, we built a more advanced Flutter app that fetches real-time weather data using an API and displays it with a user-friendly interface. We covered:

  • Setting up an advanced UI with Flutter.

  • Integrating an external API to fetch real-time data.

  • Managing state with the provider package.

Next Steps

  • Add error handling for network requests.

  • Implement additional features like weather forecasts.

  • Explore other state management solutions like bloc or riverpod.

Comments

Please log in to leave a comment.

Continue Reading:

Building a Modern Web Application with React and Redux

Published on August 05, 2024

javascript

Weather App with Node.js

Published on August 08, 2024

javascript

Introduction to Flutter and Dart

Published on August 12, 2024

dart

Comprehensive React Libraries Cheatsheet

Published on August 21, 2024

Building a Custom E-commerce Platform with Laravel and Vue.js

Published on August 27, 2024

javascriptphp

JavaScript Tutorial for Mobile App Development

Published on September 02, 2024

javascript

AJAX with JavaScript: A Practical Guide

Published on September 18, 2024

javascript

POST Request with Fetch API and JSON Data

Published on January 26, 2024

javascript