You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 15:31:01