【问题标题】:Osmdroid Marker and Json AndroidOsmdroid 标记和 Json Android
【发布时间】:2018-04-11 18:18:18
【问题描述】:

我正在使用 osmdroid 库和 android http 请求。所以我正在做的是用标记填充地图,其中纬度和经度是从服务器上的数据库中获取的。问题 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);



    }

因此,在上面的代码中,我在“for”内创建了标记,并在完成后调用 onClick 方法。但是当我这样做时,并不是所有的标记都在点击时起作用,只有最后一个被创建。 有人知道该怎么做吗?拜托,非常感谢您的帮助。

【问题讨论】:

    标签: android osmdroid


    【解决方案1】:

    我会尝试详细解释,你做错了什么,因为你似乎缺少一些关于 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 的实例)

    【讨论】:

    • 感谢您的重播和详细的解释。我再次查看我的代码,发现一些错误的编码,如哈希图。我创建了另一种方法,在该方法中我在地图上添加标记,并在其中为每个标记调用 onCLickListener 的标记列表循环。感谢您的帮助。
    【解决方案2】:

    只有最后一个标记具有 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;
                }
            });
    
    
            }
    

    【讨论】:

    • 感谢您的重播。对不起,如果我不清楚。但我仍然对答案感到困惑。在我的代码中,我通过 onResponse 中从服务器获取的经纬度数据创建标记。从上面的方法,我不明白如何在地图上创建和显示标记。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    相关资源
    最近更新 更多