Flutter中RangeError(index)异常排查:空列表索引0访问问题
问题分析与解决方案
错误日志
[错误:flutter/lib/ui/ui_dart_state.cc(198)] 未处理异常:RangeError (索引):无效值:有效取值范围为空:0
E/flutter (11420): #0 List.[] (dart:core-patch/growable_array.dart:264:36)
E/flutter (11420): #1 LocationService.getPlaceId (package:ridesharingv1/models/location_service.dart:15:37)
相关代码
import 'dart:convert' as convert; import 'package:http/http.dart' as http; class LocationService { // LocationService(); final String _apiKey = 'AIza...'; Future<String> getPlaceId(String input) async { final String url = 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=$input&inputted=textquery&fields=place_id&key=$_apiKey'; var response = await http.get(Uri.parse(url)); // if (response.statusCode == 200) { var json = convert.jsonDecode(response.body); var placeId = json['candidates'][0]['place_id'] as String; print(placeId); return placeId; // } else { // throw Exception('Failed to load place id'); // } } // Future<Map<String, dynamic>> getPlace(String input) async { // final placeId = await getPlace(input); // final String url = // 'https://maps.googleapis.com/maps/api/place/details/json?place_id=$placeId&fields=name,formatted_address,geometry&key=$_apiKey'; // var response = await http.get(Uri.parse(url)); // // // if (response.statusCode == 200) { // final json = convert.jsonDecode(response.body); // // var result = json['result'] as Map<String, dynamic>; // print(result); // return result; // // } else { // // throw Exception('Failed to load place'); // // } // } }
问题描述
在Flutter项目中调用Google Places API获取place_id时触发RangeError(index)异常,原因是代码直接访问json['candidates'][0],未判断candidates列表是否为空,当请求返回的候选结果为空时就会出现该异常。
解决方案
从边界判断、HTTP状态校验、异常捕获三个层面优化代码即可解决问题:
- 添加候选结果空判断:在访问
candidates[0]前,先检查json['candidates']是否为非空列表,避免索引越界 - 恢复HTTP状态码校验:处理非200状态的请求,覆盖请求失败、API限流等场景
- 添加异常捕获:捕获JSON解析、API请求中的异常,返回更明确的错误提示
- 修正URL参数错误:原URL中
inputted是拼写错误,正确参数为inputtype,该错误也可能导致返回空结果
优化后的代码如下:
import 'dart:convert' as convert; import 'package:http/http.dart' as http; class LocationService { final String _apiKey = 'AIza...'; Future<String> getPlaceId(String input) async { final String url = 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=$input&inputtype=textquery&fields=place_id&key=$_apiKey'; try { var response = await http.get(Uri.parse(url)); // 校验HTTP请求状态 if (response.statusCode != 200) { throw Exception('请求失败,状态码:${response.statusCode}'); } var json = convert.jsonDecode(response.body); // 检查candidates列表是否存在且非空 if (json['candidates'] == null || (json['candidates'] as List).isEmpty) { throw Exception('未找到匹配的地点,请检查输入内容'); } var placeId = json['candidates'][0]['place_id'] as String; print(placeId); return placeId; } catch (e) { print('获取place_id失败:$e'); rethrow; // 向上抛出异常,让调用方处理 } } }
内容的提问来源于stack exchange,提问作者Nabaraj Bhandari
相关产品推荐
相关产品推荐

