198 lines
5.6 KiB
Dart
198 lines
5.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import '../models/weather.dart';
|
|
import '../services/weather_service.dart';
|
|
|
|
class WeatherProvider with ChangeNotifier {
|
|
final WeatherService _weatherService = WeatherService();
|
|
|
|
Weather? _currentWeather;
|
|
List<WeatherForecast> _forecast = [];
|
|
bool _isLoading = false;
|
|
String? _error;
|
|
String _selectedLocation = '';
|
|
List<String> _favoriteLocations = [];
|
|
|
|
// Getters
|
|
Weather? get currentWeather => _currentWeather;
|
|
List<WeatherForecast> get forecast => _forecast;
|
|
bool get isLoading => _isLoading;
|
|
String? get error => _error;
|
|
String get selectedLocation => _selectedLocation;
|
|
List<String> get favoriteLocations => _favoriteLocations;
|
|
|
|
WeatherProvider() {
|
|
_loadFavoriteLocations();
|
|
refreshWeather();
|
|
}
|
|
|
|
// 刷新天气数据
|
|
Future<void> refreshWeather({String? location}) async {
|
|
_setLoading(true);
|
|
_error = null;
|
|
|
|
try {
|
|
// 获取当前天气
|
|
final weather = await _weatherService.getCurrentWeather(
|
|
location: location,
|
|
);
|
|
if (weather != null) {
|
|
_currentWeather = weather;
|
|
_selectedLocation = weather.location;
|
|
|
|
// 获取预报
|
|
final forecastData = await _weatherService.getWeatherForecast(
|
|
location: location,
|
|
);
|
|
_forecast = forecastData;
|
|
|
|
// 保存最后选择的位置
|
|
await _saveLastLocation(_selectedLocation);
|
|
} else {
|
|
_error = 'Unable to get weather data, please check network connection';
|
|
}
|
|
} catch (e) {
|
|
_error = 'Failed to get weather data: $e';
|
|
} finally {
|
|
_setLoading(false);
|
|
}
|
|
}
|
|
|
|
// 根据城市名获取天气
|
|
Future<void> getWeatherByCity(String cityName) async {
|
|
await refreshWeather(location: cityName);
|
|
}
|
|
|
|
// 搜索城市
|
|
Future<List<Map<String, dynamic>>> searchCities(String query) async {
|
|
if (query.isEmpty) return [];
|
|
|
|
try {
|
|
return await _weatherService.searchLocations(query);
|
|
} catch (e) {
|
|
debugPrint('搜索城市失败: $e');
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// 添加到收藏位置
|
|
Future<void> addToFavorites(String location) async {
|
|
if (!_favoriteLocations.contains(location)) {
|
|
_favoriteLocations.add(location);
|
|
await _saveFavoriteLocations();
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
// 从收藏位置移除
|
|
Future<void> removeFromFavorites(String location) async {
|
|
_favoriteLocations.remove(location);
|
|
await _saveFavoriteLocations();
|
|
notifyListeners();
|
|
}
|
|
|
|
// 检查是否为收藏位置
|
|
bool isFavorite(String location) {
|
|
return _favoriteLocations.contains(location);
|
|
}
|
|
|
|
// 获取收藏位置的天气
|
|
Future<List<Weather>> getFavoriteWeathers() async {
|
|
List<Weather> weathers = [];
|
|
|
|
for (String location in _favoriteLocations) {
|
|
try {
|
|
final weather = await _weatherService.getWeatherByCity(location);
|
|
if (weather != null) {
|
|
weathers.add(weather);
|
|
}
|
|
} catch (e) {
|
|
debugPrint('获取收藏位置天气失败: $location - $e');
|
|
}
|
|
}
|
|
|
|
return weathers;
|
|
}
|
|
|
|
// 设置加载状态
|
|
void _setLoading(bool loading) {
|
|
_isLoading = loading;
|
|
notifyListeners();
|
|
}
|
|
|
|
// 保存收藏位置
|
|
Future<void> _saveFavoriteLocations() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setStringList('favorite_locations', _favoriteLocations);
|
|
}
|
|
|
|
// 加载收藏位置
|
|
Future<void> _loadFavoriteLocations() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
_favoriteLocations = prefs.getStringList('favorite_locations') ?? [];
|
|
notifyListeners();
|
|
}
|
|
|
|
// 保存最后选择的位置
|
|
Future<void> _saveLastLocation(String location) async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString('last_location', location);
|
|
}
|
|
|
|
// 清除错误
|
|
void clearError() {
|
|
_error = null;
|
|
notifyListeners();
|
|
}
|
|
|
|
// 获取天气图标对应的本地图标
|
|
IconData getWeatherIcon(String condition) {
|
|
final lowerCondition = condition.toLowerCase();
|
|
|
|
if (lowerCondition.contains('sunny') || lowerCondition.contains('clear')) {
|
|
return Icons.wb_sunny;
|
|
} else if (lowerCondition.contains('cloud')) {
|
|
return Icons.cloud;
|
|
} else if (lowerCondition.contains('rain') ||
|
|
lowerCondition.contains('drizzle')) {
|
|
return Icons.grain;
|
|
} else if (lowerCondition.contains('snow')) {
|
|
return Icons.ac_unit;
|
|
} else if (lowerCondition.contains('thunder') ||
|
|
lowerCondition.contains('storm')) {
|
|
return Icons.flash_on;
|
|
} else if (lowerCondition.contains('fog') ||
|
|
lowerCondition.contains('mist')) {
|
|
return Icons.blur_on;
|
|
} else if (lowerCondition.contains('wind')) {
|
|
return Icons.air;
|
|
} else {
|
|
return Icons.wb_cloudy;
|
|
}
|
|
}
|
|
|
|
// 获取天气颜色主题
|
|
Color getWeatherColor(String condition) {
|
|
final lowerCondition = condition.toLowerCase();
|
|
|
|
if (lowerCondition.contains('sunny') || lowerCondition.contains('clear')) {
|
|
return Colors.orange;
|
|
} else if (lowerCondition.contains('cloud')) {
|
|
return Colors.grey;
|
|
} else if (lowerCondition.contains('rain') ||
|
|
lowerCondition.contains('drizzle')) {
|
|
return Colors.blue;
|
|
} else if (lowerCondition.contains('snow')) {
|
|
return Colors.lightBlue;
|
|
} else if (lowerCondition.contains('thunder') ||
|
|
lowerCondition.contains('storm')) {
|
|
return Colors.purple;
|
|
} else if (lowerCondition.contains('fog') ||
|
|
lowerCondition.contains('mist')) {
|
|
return Colors.blueGrey;
|
|
} else {
|
|
return Colors.grey;
|
|
}
|
|
}
|
|
}
|