날씨 앱: 앞으로 3일
Coddy Flutter 여정의 데이터와 네트워크 섹션에 포함된 레슨. 27개 중 24번째.
도시에 대한 응답에는 예보도 들어 있습니다. 객체 안에 JSON 목록이 있으며, 하루에 항목 하나씩 포함됩니다.
"forecast": [
{"date": "2026-10-20", "condition": "Cloudy", "high": 22, "low": 15},
...
]객체 안의 목록은 독립적인 목록과 같은 방식으로 읽습니다. as List<dynamic>로 꺼낸 다음, 각 항목에 자체 fromJson을 적용해 map합니다. 파일 아래쪽의 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')는 이를 요일의 전체 이름인 화요일로 바꿉니다. Column의 children 안에 for를 넣으면 날짜별로 행이 하나씩 만들어집니다.
챌린지
중급현재 날씨 아래에 다음 3일을 표시하세요:
- import
package:intl/intl.dart SizedBox(height: 32)뒤에 날짜별로Row를 하나씩 표시하세요.Expanded안에DateFormat('EEEE')를 사용한 요일을 표시하고, 그다음 최고 기온과 최저 기온을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,
);
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
데이터와 네트워크의 모든 레슨
직접 연습해 보세요: 온라인 Flutter 컴파일러