我正在使用osmdroid库和android http请求。所以我正在做的是用标记填充地图,其中lat和long是从服务器上的数据库获得的。问题ID:如何从我执行请求的方法中调用marker.setOnClickListener。 这是我的代码:
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONArray obj = new JSONArray(response);
for (int i = 0; i < obj.length(); i++) {
JSONObject primer = obj.getJSONObject(i);
double latitud = primer.getDouble(TAG_Latitud);
double longitude = primer.getDouble(TAG_Longitude);
marker = new Marker(map);
marker.setPosition(new GeoPoint(latitud, longitude));
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
mHashMap.put(marker, i);
Terrenos.add(terrenos);
}
marker.setOnMarkerClickListener(new Marker.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker, MapView mapView) {
Intent intent = new Intent(Osmdroid.this, Activity2.class);
startActivity(intent);
return false;
}
});
map.getOverlays().add(marker);
} catch (JSONException e) {
Toast.makeText(Osmdroid.this,"Something Wrong", Toast.LENGTH_LONG).show();
Log.w("exception", e.toString());
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(Osmdroid.this,"Something Wrong",Toast.LENGTH_LONG).show();
Log.w("Error", "No hay respuesta en http");
}
});
queue.add(stringRequest);
}
因此,在上面的代码中,我在&#39; for&#39;中创建了标记,并在完成后调用onClick方法。但是当我这样做时,并非所有标记在点击时都有效,只有最后一个创建。 有人知道该怎么办?拜托,我真的很感激你的帮助。
答案 0 :(得分:0)
只有最后一个标记有onClick,因为你只是将它设置为它。
在每个循环中,标记对象获得新的引用marker = new Marker(map);
。因为在最后一次循环时,标记对象包含最后一个引用,而onClick方法只是设置它。
要解决此问题,您只需在循环中设置onClick
和map.getOverlays().add(marker)
。
public void onResponse(String response) {
try {
JSONArray obj = new JSONArray(response);
for (int i = 0; i < obj.length(); i++) {
JSONObject primer = obj.getJSONObject(i);
double latitud = primer.getDouble(TAG_Latitud);
double longitude = primer.getDouble(TAG_Longitude);
marker = new Marker(map);
marker.setPosition(new GeoPoint(latitud, longitude));
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
map.getOverlays().add(marker);
mHashMap.put(marker, i);
Terrenos.add(terrenos);
marker.setOnMarkerClickListener(new Marker.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker, MapView mapView) {
Intent intent = new Intent(Osmdroid.this, Activity2.class);
startActivity(intent);
return false;
}
});
}
答案 1 :(得分:0)
我会试着详细解释一下,你做错了什么,因为你似乎缺少一些关于OOP编程,变量等的基础知识。
出了什么问题:
在循环中创建多个Marker类型的对象,但名为marker
的变量仅存储对Marker类型的一个对象的引用。您在循环结束时重新使用此变量,在每次迭代中分配另一个类Marker(另一个Marker类型的对象,具有自己的个人内存块)。
循环结束后,您的变量仍然存在并指向一个对象 - 它是Marker实例创建的最后一个对象,因为它是分配给名为marker
的变量的最后一个值。您正在将OnMarkerClickListener分配给此唯一对象。
如何修复
您希望在已创建的Marker的每个实例上调用方法setOnMarkerClickListener
(分配OnMarkerClickListener)。这样做的方法与创建相同:使用循环。你基本上有两个选择:
1)重用已经在代码中的循环并在那里分配监听器。这是最简单的解决方案,因为您可以在源代码中稍微调整一下这个任务,它会起作用:
for (int i = 0; i < obj.length(); i++) {
JSONObject primer = obj.getJSONObject(i);
double latitud = primer.getDouble(TAG_Latitud);
double longitude = primer.getDouble(TAG_Longitude);
marker = new Marker(map);
marker.setPosition(new GeoPoint(latitud, longitude));
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
mHashMap.put(marker, i);
Terrenos.add(terrenos);
marker.setOnMarkerClickListener(new Marker.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker, MapView mapView) {
Intent intent = new Intent(Osmdroid.this, Activity2.class);
startActivity(intent);
return false;
}
});
}
map.getOverlays().add(marker);
这不是如何做到这一点的最佳方式。为每个标记创建了一个新的侦听器实例,因此浪费了一点内存。但是您可以在循环之前创建一个侦听器实例,将其存储在变量中并将相同的对象分配给所有标记。一旦你开始工作,试着把它想象成一种改进。
2)您可以在某处存储标记并创建另一个循环,您可以在其中分配监听器。您可以拥有包含所有标记列表的变量(或类中的字段)
List<Marker> markers = new ArrayList<>();
在循环中,创建标记后,您可以将其添加到此列表中:
for (int i = 0; i < obj.length(); i++) {
...
marker = new Marker(map);
marker.setPosition(new GeoPoint(latitud, longitude));
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
markers.add(marker); //addind to the listt
...
您可以稍后迭代列表,并为所有标记分配侦听器。尝试自己计算代码。将会有与前一种情况类似的决定:您可以为每个标记创建新的侦听器,或者为所有标记重用一个。
最后一件事:你不需要像我上面提到的那样使用列表来创建新变量,因为你已经有了包含所有标记的字段。您正在将它们用作hasmmap中的键:
mHashMap.put(marker, i);
我不知道这个hashmap的用途是什么,但是您可以通过mHasnMap.keySet()