使用非Google Places API的JSON服务查询附近地点及空指针错误修复
错误根源
你在ParserTask的onPostExecute方法中调用了空对象的size()方法,本质是JSON解析逻辑出错返回了null,加上没有做非空校验导致崩溃。
具体问题点
- JSON层级读取错误:接口返回的根对象下首先是
ArrayOfmasjid节点,你当前parseResult方法直接从根对象读取masjid数组,必然抛出JSON异常,最终返回null列表 - HashMap键名冲突:你把纬度和经度都存在了
__text同一个key下,后续的经度会直接覆盖纬度值,就算解析成功也拿不到正确的经纬度 - 数组遍历错误:
parseJsonArray方法的循环中你写死了jsonArray.get(1),每次都读取数组第二个元素,要么逻辑错误要么触发数组越界异常 - 缺失非空校验:
onPostExecute拿到解析结果后直接调用size(),同时没有判断map对象是否完成初始化(getMapAsync是异步回调,有可能接口请求完了地图还没加载好)
修复代码
修复后的JsonParser类
public class JsonParser { private HashMap<String, String> parseJsonObject(JSONObject object) { HashMap<String, String> datalist = new HashMap<>(); try { String name = object.getString("masjidName"); String latitude = object.getJSONObject("masjidLocation") .getJSONObject("coordinates") .getJSONArray("double") .getJSONObject(1) .getString("__text"); String longitude = object.getJSONObject("masjidLocation") .getJSONObject("coordinates") .getJSONArray("double") .getJSONObject(0) .getString("__text"); datalist.put("name",name); datalist.put("latitude",latitude); // 改用不同的key存经纬度 datalist.put("longitude",longitude); } catch (JSONException e) { e.printStackTrace(); } return datalist; } private List<HashMap<String,String>> parseJsonArray(JSONArray jsonArray){ List<HashMap<String,String>> datalist = new ArrayList<>(); if (jsonArray == null) return datalist; // 空数组直接返回空列表 for (int i = 0; i< jsonArray.length(); i++){ try { HashMap<String,String> data = parseJsonObject((JSONObject) jsonArray.get(i)); // 改为用循环变量i取值 datalist.add(data); } catch (JSONException e) { e.printStackTrace(); } } return datalist; } public List<HashMap<String, String>> parseResult(JSONObject object){ JSONArray jsonArray = null; try { // 先取ArrayOfmasjid节点,再取里面的masjid数组 jsonArray = object.getJSONObject("ArrayOfmasjid").getJSONArray("masjid"); } catch (JSONException e) { e.printStackTrace(); } return parseJsonArray(jsonArray); } }
修复后的ParserTask的onPostExecute方法
@Override protected void onPostExecute(List<HashMap<String, String>> hashMaps) { // 先校验map和hashMaps都不为空再执行后续逻辑 if (map == null || hashMaps == null) return; map.clear(); for (int i=0; i<hashMaps.size();i++){ HashMap<String,String> hashMapList = hashMaps.get(i); double lat = Double.parseDouble(hashMapList.get("latitude")); double lng = Double.parseDouble(hashMapList.get("longitude")); String name = hashMapList.get("name"); LatLng latLng = new LatLng(lat,lng); MarkerOptions options = new MarkerOptions(); options.position(latLng); options.title(name); map.addMarker(options); } }
额外优化建议
- 权限申请通过后再触发接口请求,你现在不管权限有没有同意都直接执行
new PlaceTask().execute(url),逻辑不合理 - 接口请求可以放在位置获取成功之后,后续可以换成传入当前经纬度查询附近地点,而不是写死查询邮编462001的地点
内容的提问来源于stack exchange,提问作者Abdul Hadi
相关产品推荐
相关产品推荐

