Flutter异常处理:输入无效城市名时如何提示错误信息
解决OpenWeatherMap地理API无效城市名的错误捕获与提示问题
问题分析
当输入无效城市名时,OpenWeatherMap的geo/1.0/direct接口会返回状态码200+空数组[],但你当前的代码仅判断了状态码是否为200,直接尝试取数组第一个元素json[0]会触发数组越界异常,无法正确识别无效城市的情况。
解决方案
1. 修改API调用函数,捕获空数组情况
更新gettingCityData函数,在解析响应后先检查数组是否为空,为空则抛出明确的错误:
Constants myConstaints = Constants(); Future<CityInfo> gettingCityData(String cityName) async { var url = Uri.parse( 'https://api.openweathermap.org/geo/1.0/direct?q=$cityName&limit=1&appid=${myConstaints.apiKey}'); var response = await http.get(url); if (response.statusCode == 200) { final List<dynamic> jsonData = jsonDecode(response.body); // 检查返回数组是否为空,为空则抛出无效城市错误 if (jsonData.isEmpty) { throw Exception('未找到指定城市,请检查输入是否正确'); } var i = CityInfo.fromJson(jsonData); return i; } else { // 处理非200状态码的错误,比如API密钥无效、请求超时等 throw Exception('请求失败:${response.statusCode}'); } }
2. 优化CityInfo构造方法(可选)
为避免后续其他场景触发数组越界,可在构造方法中增加空值检查:
class CityInfo { String name; double lat; double long; CityInfo.fromJson(List<dynamic> json) : name = json.isNotEmpty ? json[0]['name'] : '', lat = json.isNotEmpty ? json[0]['lat'].toDouble() : 0.0, long = json.isNotEmpty ? json[0]['lon'].toDouble() : 0.0; }
3. 在Provider中处理异常
修改Provider的cityName方法,捕获异常并更新错误状态,方便UI层监听:
// 在Provider类中添加错误状态变量 String? errorMessage; Future<void> cityName(String cityName) async { try { errorMessage = null; // 清空历史错误 cityInfo = await gettingCityData(cityName); notifyListeners(); } catch (e) { errorMessage = e.toString().replaceAll('Exception: ', ''); // 提取干净的错误信息 notifyListeners(); } }
4. UI层展示错误信息
在UI组件中监听Provider的errorMessage,当不为空时通过弹窗或SnackBar提示用户:
@override Widget build(BuildContext context) { final weatherProvider = Provider.of<WeatherProvider>(context); // 监听错误信息,自动弹出提示 if (weatherProvider.errorMessage != null) { WidgetsBinding.instance.addPostFrameCallback((_) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(weatherProvider.errorMessage!)), ); }); } return Scaffold( // 你的UI布局代码 ); }
或者直接在调用Provider方法时用try-catch捕获:
// 示例:按钮点击事件中调用 onPressed: () async { final provider = Provider.of<WeatherProvider>(context, listen: false); try { await provider.cityName(inputCityName); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(e.toString().replaceAll('Exception: ', ''))), ); } },
内容的提问来源于stack exchange,提问作者mohitnx
相关产品推荐
相关产品推荐

