Osmdroid Marker和Json Android

时间:2018-04-11 18:18:18

标签: android osmdroid

我正在使用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方法。但是当我这样做时,并非所有标记在点击时都有效,只有最后一个创建。 有人知道该怎么办?拜托,我真的很感激你的帮助。

2 个答案:

答案 0 :(得分:0)

只有最后一个标记有onClick,因为你只是将它设置为它。 在每个循环中,标记对象获得新的引用marker = new Marker(map);。因为在最后一次循环时,标记对象包含最后一个引用,而onClick方法只是设置它。

要解决此问题,您只需在循环中设置onClickmap.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()

访问所有标记(确切地说:对所有标记的Set实例)