Weather App: Right Now
Part of the Data and the Network section of Coddy's Flutter journey. Lesson 23 of 27.
Time to build a whole app from this section: a weather app. Over the next five lessons it shows the weather for a city right now, the next three days, an icon for each, an error screen with Try again, and a city picker.
The practice API knows three cities. /weather/lisbon answers:
{
"city": "Lisbon",
"temperature": 21,
"condition": "Sunny",
"forecast": [ ... ]
}Start with the top of the screen, and the steps you know: a class for the data, a function that fetches and decodes it, a future made once in initState, and a FutureBuilder with its three states. The Weather and DayForecast classes at the bottom of the file are written for you, with their fromJson. This lesson shows the current weather; the forecast comes in the next one.
Challenge
HardShow Lisbon's weather:
loadWeatherfetches/weather/lisbonand returnsWeather.fromJson(jsonDecode(body))- make the future once in
initState - a
FutureBuilder<Weather>shows a spinner while it loads,Could not load:and the error if it fails - with the data, a
Columnof the city (size 32), the temperature with a degree sign,21°(size 72, bold), and the condition (size 24)
Try it yourself
import 'dart:convert';
import 'package:flutter/material.dart';
import 'api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: WeatherScreen(),
);
}
}
class WeatherScreen extends StatefulWidget {
const WeatherScreen({super.key});
@override
State<WeatherScreen> createState() => _WeatherScreenState();
}
class _WeatherScreenState extends State<WeatherScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Weather')),
body: const Center(
child: Text('The weather goes here'),
),
);
}
}
class Weather {
Weather({
required this.city,
required this.temperature,
required this.condition,
required this.forecast,
});
final String city;
final int temperature;
final String condition;
final List<DayForecast> forecast;
factory Weather.fromJson(Map<String, dynamic> json) {
final days = json['forecast'] as List<dynamic>;
return Weather(
city: json['city'] as String,
temperature: json['temperature'] as int,
condition: json['condition'] as String,
forecast: days
.map((day) => DayForecast.fromJson(day as Map<String, dynamic>))
.toList(),
);
}
}
class DayForecast {
DayForecast({
required this.date,
required this.condition,
required this.high,
required this.low,
});
final DateTime date;
final String condition;
final int high;
final int low;
factory DayForecast.fromJson(Map<String, dynamic> json) {
return DayForecast(
date: DateTime.parse(json['date'] as String),
condition: json['condition'] as String,
high: json['high'] as int,
low: json['low'] as int,
);
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Data and the Network
3When Calls Fail
Catching Errors With tryThrowing an ErrorCleaning Up With finallyThe FutureBuilder Error StateA Try Again Button6Project: Weather App
Weather App: Right NowWeather App: Next Three DaysPractice on your own: Online Flutter compiler