Flutter按钮点击后调用OpenWeatherMap REST API的实现问题
在Flutter中实现按钮触发OpenWeatherMap API请求
嘿,恭喜你已经搞定了API调用的核心代码!接下来咱们把按钮点击和这个请求逻辑绑定起来,让用户一点按钮就能拿到天气数据。我给你一步步拆解具体实现:
1. 先完善你的API类(补全代码)
你已经写了基础的OpenWeatherApi类,我帮你补全URL部分,确保能正确发起请求:
class OpenWeatherApi { static const _API_KEY = "asdbaklsadfkasdlfkasdjfl"; // 记得替换成你的真实API Key Future<CurrentWeather> getCurrentWeather(String location) async { final url = Uri.parse( "https://api.openweathermap.org/data/2.5/weather?q=$location&appid=$_API_KEY&units=metric" ); final response = await http.get(url); if (response.statusCode == 200) { return CurrentWeather.fromJson(jsonDecode(response.body)); } else { throw Exception("Failed to load weather data"); } } } // 记得定义CurrentWeather模型类来解析返回的JSON class CurrentWeather { final String cityName; final double temperature; CurrentWeather({required this.cityName, required this.temperature}); factory CurrentWeather.fromJson(Map<String, dynamic> json) { return CurrentWeather( cityName: json['name'], temperature: json['main']['temp'].toDouble(), ); } }
2. 构建带按钮的页面(使用StatefulWidget)
因为要处理异步请求的状态(加载中、成功、失败),咱们用StatefulWidget来管理页面状态:
class WeatherPage extends StatefulWidget { const WeatherPage({super.key}); @override State<WeatherPage> createState() => _WeatherPageState(); } class _WeatherPageState extends State<WeatherPage> { final _api = OpenWeatherApi(); final _locationController = TextEditingController(text: "London"); // 默认城市 bool _isLoading = false; CurrentWeather? _weatherData; String? _errorMessage; // 点击按钮触发的请求方法 void _fetchWeather() async { setState(() { _isLoading = true; _errorMessage = null; }); try { final weather = await _api.getCurrentWeather(_locationController.text); setState(() { _weatherData = weather; }); } catch (e) { setState(() { _errorMessage = e.toString(); }); } finally { setState(() { _isLoading = false; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("天气查询")), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _locationController, decoration: const InputDecoration( labelText: "输入城市名称", border: OutlineInputBorder(), ), ), const SizedBox(height: 16), ElevatedButton( onPressed: _isLoading ? null : _fetchWeather, child: _isLoading ? const CircularProgressIndicator(color: Colors.white) : const Text("查询天气"), ), const SizedBox(height: 24), // 展示结果或错误信息 if (_isLoading) const Text("加载中...") else if (_errorMessage != null) Text("出错了: $_errorMessage", style: const TextStyle(color: Colors.red)) else if (_weatherData != null) Column( children: [ Text("城市: ${_weatherData!.cityName}", style: const TextStyle(fontSize: 18)), const SizedBox(height: 8), Text("温度: ${_weatherData!.temperature}°C", style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), ], ), ], ), ), ); } }
3. 注意事项
- 别忘了在
pubspec.yaml里添加依赖:http: ^1.1.0(或者最新版本),然后执行flutter pub get - 重要提示:不要把API Key硬编码在代码里!如果是正式项目,建议用环境变量或者配置文件来管理,避免泄露
- 可以根据需求扩展
CurrentWeather模型,添加更多天气信息(比如湿度、风速等)
这样一来,用户点击按钮后就会触发API请求,页面也会根据请求状态展示不同的内容啦~
内容的提问来源于stack exchange,提问作者Christopher
相关产品推荐
相关产品推荐

