修复Flutter中API数据无法随输入城市更新UI的问题
修复Flutter中OpenWeather API城市名刷新丢失问题
你的问题核心是城市名变量未与UI状态绑定,每次Widget重建(刷新、热重载)时,局部变量会被重新初始化,导致丢失用户输入的内容。以下是具体的修复方案:
基础修复方案(使用StatefulWidget)
通过StatefulWidget管理城市名状态,确保输入的城市名在Widget重建时不会丢失,同时触发API请求获取对应城市的天气数据。
完整示例代码
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class WeatherScreen extends StatefulWidget { const WeatherScreen({super.key}); @override State<WeatherScreen> createState() => _WeatherScreenState(); } class _WeatherScreenState extends State<WeatherScreen> { // 用状态变量存储城市名,初始值设为默认城市 String _cityName = 'London'; Map<String, dynamic>? _weatherData; bool _isLoading = false; final TextEditingController _cityController = TextEditingController(); // 调用OpenWeather API获取天气数据 Future<void> _fetchWeather() async { setState(() { _isLoading = true; }); // 替换为你的OpenWeather API Key const apiKey = 'YOUR_API_KEY'; final url = Uri.parse( 'https://api.openweathermap.org/data/2.5/weather?q=$_cityName&appid=$apiKey&units=metric'); try { final response = await http.get(url); if (response.statusCode == 200) { setState(() { _weatherData = json.decode(response.body); }); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('获取天气失败:${response.statusCode}')), ); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('网络错误:$e')), ); } finally { setState(() { _isLoading = false; }); } } @override void initState() { super.initState(); // 初始化时加载默认城市天气 _fetchWeather(); // 绑定输入框初始值 _cityController.text = _cityName; } @override void dispose() { // 释放控制器资源 _cityController.dispose(); super.dispose(); } @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: _cityController, decoration: const InputDecoration( labelText: '输入城市名', border: OutlineInputBorder(), suffixIcon: Icon(Icons.search), ), onSubmitted: (value) { setState(() { _cityName = value; }); _fetchWeather(); }, ), const SizedBox(height: 20), // 加载状态或天气信息展示 _isLoading ? const CircularProgressIndicator() : _weatherData != null ? Column( children: [ Text( _weatherData!['name'], style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold), ), const SizedBox(height: 10), Text( '${_weatherData!['main']['temp']}°C', style: const TextStyle(fontSize: 48), ), Text( _weatherData!['weather'][0]['description'], style: const TextStyle(fontSize: 18), ), ], ) : const Text('暂无数据'), ], ), ), ); } }
关键修复点
- 状态变量存储城市名:将
_cityName定义为State类的成员变量,而非局部变量,确保Widget重建时状态被保留。 - TextEditingController绑定输入框:输入框内容与状态同步,即使Widget重建,输入框也能显示当前城市名。
- 提交输入触发更新:用户提交城市名时,先更新
_cityName状态,再调用API获取对应城市的天气数据。 - 初始化与资源释放:
initState中加载默认城市天气并绑定输入框初始值,dispose中释放控制器资源避免内存泄漏。
进阶方案(跨页面共享状态)
如果需要在多个页面共享城市名状态,可以使用状态管理库(如Riverpod、Provider或Bloc),将城市名状态提升到全局或父级组件中,避免每次页面重建丢失数据。
内容的提问来源于stack exchange,提问作者The Synergist
相关产品推荐
相关产品推荐

