如何获取特定Polyline数据?解决点击时Toast显示异常问题
针对你提出的两个问题,我来给你详细拆解解答:
要获取特定Polyline的关联数据,最直接且通用的方式是利用Polyline自带的setTag()和getTag()方法来绑定自定义数据。
简单来说,你在创建Polyline的时候,把和这条Polyline相关的所有数据(比如坐标集合、自定义ID、路线描述等)打包成一个对象,通过setTag()绑定到Polyline实例上。之后不管是点击事件还是其他场景需要获取数据,直接调用getTag()就能拿到对应的内容。
举个代码示例:
// 先定义一个自定义数据类,用来存储Polyline的关联信息 class PolylineData { private String desc; private List<LatLng> points; public PolylineData(String desc, List<LatLng> points) { this.desc = desc; this.points = points; } public String getDesc() { return desc; } public List<LatLng> getPoints() { return points; } } // 创建Polyline时绑定数据 Polyline myPolyline = map.addPolyline(new PolylineOptions() .add(new LatLng(39.9042, 116.4074), new LatLng(31.2304, 121.4737)) .width(5) .color(Color.BLUE)); PolylineData data = new PolylineData("北京到上海的路线", myPolyline.getPoints()); myPolyline.setTag(data); // 后续获取特定Polyline的数据 PolylineData retrievedData = (PolylineData) myPolyline.getTag(); if (retrievedData != null) { String routeDesc = retrievedData.getDesc(); List<LatLng> routePoints = retrievedData.getPoints(); // 这里就可以用拿到的数据做你需要的操作了 }
如果你的地图SDK支持通过ID查找Polyline,也可以先通过ID获取到目标Polyline实例,再用上述方法提取数据。
这个问题是循环创建Polyline并设置点击监听时的典型变量引用陷阱,我帮你分析下原因和解决办法:
问题根源
如果你是在循环里批量创建Polyline,并且直接在点击监听里引用循环变量(比如data),那所有监听都会指向最后一次循环的变量值。这是因为Java的匿名内部类捕获的是变量的引用,而循环里的变量是同一个引用不断被重新赋值,最终所有监听都绑定了最后一个变量的引用。
错误示例(你大概率是这么写的):
List<PolylineData> dataList = getYourPolylineData(); for (PolylineData data : dataList) { Polyline polyline = map.addPolyline(new PolylineOptions() .addAll(data.getPoints()) .width(5)); // 错误:直接引用循环变量data polyline.setOnClickListener(new Polyline.OnClickListener() { @Override public void onClick(Polyline polyline) { Toast.makeText(context, data.getDesc(), Toast.LENGTH_SHORT).show(); } }); }
两种解决办法
方法一:用局部变量捕获当前循环的数值
在循环内部创建一个局部变量,把当前循环的data赋值给它,让匿名内部类捕获这个局部变量的引用,这样每个监听都会绑定当前循环的正确数据:
for (PolylineData data : dataList) { PolylineData currentData = data; // 关键:创建局部变量保存当前值 Polyline polyline = map.addPolyline(new PolylineOptions() .addAll(data.getPoints()) .width(5)); polyline.setOnClickListener(new Polyline.OnClickListener() { @Override public void onClick(Polyline polyline) { Toast.makeText(context, currentData.getDesc(), Toast.LENGTH_SHORT).show(); } }); }
方法二:利用Polyline的Tag获取对应数据(更推荐)
既然我们之前已经知道可以给Polyline绑定Tag数据,那直接在点击监听里从当前点击的Polyline实例中提取Tag,完全避免变量引用的问题,这种方法更稳妥:
for (PolylineData data : dataList) { Polyline polyline = map.addPolyline(new PolylineOptions() .addAll(data.getPoints()) .width(5)); polyline.setTag(data); // 绑定数据到Polyline polyline.setOnClickListener(new Polyline.OnClickListener() { @Override public void onClick(Polyline polyline) { PolylineData clickedData = (PolylineData) polyline.getTag(); if (clickedData != null) { Toast.makeText(context, clickedData.getDesc(), Toast.LENGTH_SHORT).show(); } } }); }
如果是用全局的OnPolylineClickListener(比如map.setOnPolylineClickListener(...)),那同样在onPolylineClick(Polyline polyline)方法里通过polyline.getTag()获取对应数据即可,绝对不会出现混淆。
内容的提问来源于stack exchange,提问作者YaZao RuZakiaga

