Hava Durumu Uygulaması: Yeniden Dene
Coddy'nin Flutter Journey'sinin Veri ve Ağ bölümünün bir parçası. Ders 26 / 27.
Hava durumu uygulamaları trenlerde, tünellerde ve dağlarda açılır. Sinyal olmadığında uygulama bunu açıkça söylemeli ve hiç bitmeyen bir dönen simge ya da bir satır hata metni yerine geri dönmenin bir yolunu sunmalıdır.
Hataya kendine ait küçük bir ekran ver: bir simge, herkesin anlayacağı bir cümle, altındaki ayrıntılar ve Tekrar dene düğmesi; bu düğme setState içinde yeni bir future oluşturur. build kısa kalsın diye bunu buildWeather metodunun yanına, kendi metodu olan buildError içine koy.
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
if (snapshot.hasError) {
return buildError(snapshot.error!);
}
return buildWeather(snapshot.data!);Önce ConnectionState.waiting durumunu kontrol etmek, ikinci deneme de dahil olmak üzere her yükleme sırasında dönen simgeyi gösterir. Future tamamlandığında ya bir hata ya da veri olur; bu nedenle son satırda snapshot.data! kullanılabilir.
Önizlemede görmek için offline = true; ifadesini main metodunun ilk satırı olarak yaz ve Run düğmesine bas. Check düğmesine basmadan önce bu satırı kaldır.
Görev
OrtaUygulamaya bir hata ekranı ekle:
- bir
buildError(Object error)yöntemi:Icons.cloud_off(boyut 64),Could not load the weather(boyut 20), hata metni ve bir Try again düğmesi setStateiçinde yeni birloadWeather()ayarlayan birtryAgainyöntemi- oluşturucuda önce
ConnectionState.waitingdurumunu, sonra hatayı kontrol et ve ardından hava durumunu göster
Kendin dene
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:intl/intl.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));
}
IconData iconFor(String condition) {
return switch (condition) {
'Sunny' => Icons.wb_sunny,
'Cloudy' => Icons.cloud,
'Rainy' => Icons.umbrella,
'Snowy' => Icons.ac_unit,
_ => Icons.help_outline,
};
}
@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)),
Icon(iconFor(weather.condition), size: 96, color: Colors.orange),
Text(
'${weather.temperature}°',
style: const TextStyle(fontSize: 72, fontWeight: FontWeight.bold),
),
Text(weather.condition, style: const TextStyle(fontSize: 24)),
const SizedBox(height: 32),
for (final day in weather.forecast)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 8),
child: Row(
children: [
Icon(iconFor(day.condition)),
const SizedBox(width: 16),
Expanded(
child: Text(
DateFormat('EEEE').format(day.date),
style: const TextStyle(fontSize: 18),
),
),
Text('${day.high}° / ${day.low}°', style: const TextStyle(fontSize: 18)),
],
),
),
],
);
}
}
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,
);
}
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Veri ve Ağ bölümündeki tüm dersler
3Çağrılar Başarısız Olduğunda
try ile Hataları YakalamaHata Fırlatmafinally ile TemizlemeFutureBuilder Hata DurumuYeniden Dene Düğmesi6Proje: Hava Durumu Uygulaması
Hava Durumu Uygulaması: Şu AnHava Durumu Uygulaması: Önümüzdeki Üç GünKendi başına pratik yap: Online Flutter derleyicisi