Menu
CoddyTech

Приложение «Погода»: ближайшие три дня

Часть раздела Данные и сеть путешествия по Flutter на Coddy. Урок 24 из 27.

В ответе для города также содержится прогноз: список JSON внутри объекта, по одному элементу на каждый день.

"forecast": [
  {"date": "2026-10-20", "condition": "Cloudy", "high": 22, "low": 15},
  ...
]

Список внутри объекта читается так же, как и отдельный список: извлеки его как as List<dynamic>, затем обработай каждый элемент с помощью map, передав его в собственный fromJson. Посмотри на Weather.fromJson в конце файла: там это уже делается, поэтому weather.forecast имеет тип List<DayForecast>.

final days = json['forecast'] as List<dynamic>;

forecast: days
    .map((day) => DayForecast.fromJson(day as Map<String, dynamic>))
    .toList(),

У каждого дня есть значение типа DateTime. DateFormat('EEEE') преобразует его в полное название дня недели, например Tuesday. Цикл for внутри дочерних элементов Column создаёт отдельную строку для каждого дня.

challenge icon

Задание

Средне

Под текущей погодой покажи прогноз на следующие три дня:

  • подключи package:intl/intl.dart
  • после SizedBox(height: 32) добавь по одному Row на каждый день: день недели с помощью DateFormat('EEEE') внутри Expanded, затем максимальную и минимальную температуры в формате 22° / 15°
  • добавь к каждой строке отступы по 32 пикселя слева и справа

Попробуйте сами

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> {
  late Future<Weather> _weather;

  @override
  void initState() {
    super.initState();
    _weather = loadWeather();
  }

  Future<Weather> loadWeather() async {
    final body = await fetch('/weather/lisbon');
    return Weather.fromJson(jsonDecode(body));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Weather')),
      body: Center(
        child: FutureBuilder<Weather>(
          future: _weather,
          builder: (context, snapshot) {
            if (snapshot.hasError) {
              return Text('Could not load: ${snapshot.error}');
            }
            if (snapshot.hasData) {
              return buildWeather(snapshot.data!);
            }
            return const CircularProgressIndicator();
          },
        ),
      ),
    );
  }

  Widget buildWeather(Weather weather) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text(weather.city, style: const TextStyle(fontSize: 32)),
        Text(
          '${weather.temperature}°',
          style: const TextStyle(fontSize: 72, fontWeight: FontWeight.bold),
        ),
        Text(weather.condition, style: const TextStyle(fontSize: 24)),
      ],
    );
  }
}

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,
    );
  }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Данные и сеть

Потренируйтесь самостоятельно: Онлайн-компилятор Flutter