how to show location pin of the visible portion of a mapview in android?
Asked Answered
B

4

9

Here is my asynctask part where I am putting pin in some location parsed from an XML. This is doing fine for a small location data set but takes a long time when the location data set is large.

private class MapLoader extends AsyncTask<Void, Void, Void> {
    ProgressDialog dialog;
    ArrayList<POI>[] mappoiList;

    @Override
    protected void onPreExecute() {
        mapOverlays = mapview.getOverlays();
        dialog = new ProgressDialog(MainActivity.this);
        dialog.show();
    }

    @Override
    protected Void doInBackground(Void... params) {

        try {

            URL url = new URL(MainActivity.baseUrl
                    + "latitude=40.9192799&longitude=-74.0657508&distance=20");
            
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();
            XMLReader xr = sp.getXMLReader();
            ParserHandler parserHandler = new ParserHandler();
            xr.setContentHandler(parserHandler);
            xr.parse(new InputSource(url.openStream()));
            Log.d("Thread", url.toString());
            basicItems = parserHandler.getBasicItems();
            featuredItems = parserHandler.getFeaturedItems();
            restaurants = parserHandler.getRestaurants();
            mapvisibleList = new ArrayList<POI>();
            mappoiList = new ArrayList[2];
            mappoiList[0] = new ArrayList<POI>();
            mappoiList[1] = new ArrayList<POI>();

            for (int i = 0; i < featuredItems.size(); i++) {

                POI poi = new POI(featuredItems.get(i), 1);
                mappoiList[0].add(poi);
            }
            for (int i = 0; i < restaurants.size(); i++) {

                POI poi = new POI(restaurants.get(i), 2);
                mappoiList[0].add(poi);
            }
            for (int i = 0; i < basicItems.size(); i++) {

                POI poi = new POI(basicItems.get(i), 0);
                mappoiList[1].add(poi);
            }

            for (int i = 0; i < mappoiList[0].size(); i++) {
                if (mappoiList[0] != null) {
                    mapvisibleList.add(mappoiList[0].get(i));
                }
            }

            for (int i = 0; i < mappoiList[1].size(); i++) {
                if (mappoiList[1] != null) {
                    mapvisibleList.add(mappoiList[1].get(i));
                }
            }
            for (FeaturedItem item : featuredItems) {
                Log.d("FEATURED",
                        item.getName() + "Distance: " + item.getDistance());
            }
            for (Restaurant item : restaurants) {
                Log.d("RESTAURANTS",
                        item.getName() + "Distance: " + item.getDistance());
            }
            for (BasicItem item : basicItems) {
                Log.d("BASIC",
                        item.getName() + "Distance: " + item.getDistance());
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
            showErrorDialog("Error", "Malformed URL Error Occurred");
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
            showErrorDialog("Error",
                    "Parser Configuration Problem Occurred");
        } catch (SAXException e) {
            e.printStackTrace();
            showErrorDialog("Error", "SAX Parser Error Occurred");
        } catch (IOException e) {
            e.printStackTrace();
            showErrorDialog("Error", "IOException Occurred");
        } catch (Exception e) {
            e.printStackTrace();
        }

        GlobalData.gBasicItems = basicItems;
        GlobalData.gFeaturedItems = featuredItems;
        GlobalData.gRestaurants = restaurants;

        if (currentLocation != null) {
            int curLat = (int) (currentLocation.getLatitude() * 1e6);
            int curLon = (int) (currentLocation.getLongitude() * 1e6);
            GeoPoint gp = new GeoPoint(curLat, curLon);
            mapControl.animateTo(gp);

            mapControl.setZoom(14);
            OverlayItem item = new OverlayItem(gp, "My Location",
                    "My Location");

            itemizedOverlay1 = new MyItemizedOverlay(drawableFeature,
                    MainActivity.this, mappoiList[0]);
            itemizedOverlay2 = new MyItemizedOverlay(drawableBasic,
                    MainActivity.this, mappoiList[1]);
            itemizedOverlay3 = new MyItemizedOverlay(drawableCurrent,
                    MainActivity.this, mappoiList[0]);
            Log.i("asyncbasic", "" + basicItems.size());
            Log.i("asyncfeatured", "" + featuredItems.size());
            Log.i("asyncres", "" + restaurants.size());
            if (featuredItems != null) {
                int featuredLength = featuredItems.size();
                for (int i = 0; i < featuredLength; i++) {
                    FeaturedItem fItem = featuredItems.get(i);
                    int lat = (int) (Double
                            .parseDouble(fItem.getLatitude()) * 1e6);
                    int lon = (int) (Double.parseDouble(fItem
                            .getLongitude()) * 1e6);
                    OverlayItem oItem = new OverlayItem(new GeoPoint(lat,
                            lon), fItem.getName(), "Feature");
                    itemizedOverlay1.addOverlay(oItem);
                    Log.i("Map over lay", "Finished one featured");
                }
            }
            if (basicItems != null) {
                int basicLength = basicItems.size();
                for (int i = 0; i < basicLength; i++) {
                    BasicItem bItem = basicItems.get(i);
                    int lat = (int) (Double
                            .parseDouble(bItem.getLatitude()) * 1e6);
                    int lon = (int) (Double.parseDouble(bItem
                            .getLongitude()) * 1e6);
                    OverlayItem oItem = new OverlayItem(new GeoPoint(lat,
                            lon), bItem.getName(), "Basic");
                    itemizedOverlay2.addOverlay(oItem);
                    Log.i("Map over lay", "Finished one Basic");

                }
            }
            if (restaurants != null) {
                int resLength = restaurants.size();
                for (int i = 0; i < resLength; i++) {
                    Restaurant res = restaurants.get(i);
                    int lat = (int) (Double.parseDouble(res.getLatitude()) * 1e6);
                    int lon = (int) (Double.parseDouble(res.getLongitude()) * 1e6);
                    OverlayItem oItem = new OverlayItem(new GeoPoint(lat,
                            lon), res.getName(), "Restaurant");
                    itemizedOverlay1.addOverlay(oItem);
                    Log.i("Map over lay", "Finished one Restaurant");
                }
            }

            itemizedOverlay3.addOverlay(item);
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        mapOverlays.clear();
        mapOverlays.add(itemizedOverlay1);
        mapOverlays.add(itemizedOverlay2);
        mapOverlays.add(itemizedOverlay3);
        mapview.postInvalidate();
        dialog.dismiss();

    }
}

I learned about using getLatitudeSpan and getLongitudeSpan to get rid of this problem, but I am not too clear on where and how to use it in my async task. Any suggestions?

Baxie answered 10/2, 2013 at 12:57 Comment(3)
Can anybody help? I got no reason why anyone is not at least giving a single reply :(Baxie
try profiling your application to see where the time is being eaten up. And can you define 'large number'? I.e. is this 10 or 1000?Crystallization
1) avoid using so many loops try to combine them. 2) Optimize your ParserHandler to return the data in final form (ArrayList<POI> and new ArrayList[2]) to avoid running the DataSets so many times!Canker
A
0

Please give exact data size where the time taken is long, Also try profiling the code to see time taken for each code block.

But looking at the code, the looping through all those variables would have a significant effect on time if the data being operated on increased,

try simplifying/combining the loops,

e.g this loop

        for (int i = 0; i < featuredItems.size(); i++) {

                POI poi = new POI(featuredItems.get(i), 1);
                mappoiList[0].add(poi);
            }

and this one

       if (featuredItems != null) {
                  int featuredLength = featuredItems.size();
                   for (int i = 0; i < featuredLength; i++) {
                    FeaturedItem fItem = featuredItems.get(i);
                    int lat = (int) (Double
                            .parseDouble(fItem.getLatitude()) * 1e6);
                    int lon = (int) (Double.parseDouble(fItem
                            .getLongitude()) * 1e6);
                    OverlayItem oItem = new OverlayItem(new GeoPoint(lat,
                            lon), fItem.getName(), "Feature");
                    itemizedOverlay1.addOverlay(oItem);
                    Log.i("Map over lay", "Finished one featured");
                }
            }

can't be combined?

also this loop

   for (int i = 0; i < basicItems.size(); i++) {

                POI poi = new POI(basicItems.get(i), 0);
                mappoiList[1].add(poi);
                }

and this

        if (basicItems != null) {
                int basicLength = basicItems.size();
                for (int i = 0; i < basicLength; i++) {
                    BasicItem bItem = basicItems.get(i);
                    int lat = (int) (Double
                            .parseDouble(bItem.getLatitude()) * 1e6);
                    int lon = (int) (Double.parseDouble(bItem
                            .getLongitude()) * 1e6);
                    OverlayItem oItem = new OverlayItem(new GeoPoint(lat,
                            lon), bItem.getName(), "Basic");
                    itemizedOverlay2.addOverlay(oItem);
                    Log.i("Map over lay", "Finished one Basic");

                }
            }

can also be combined,

Aubergine answered 10/2, 2013 at 12:57 Comment(0)
W
0

I think problem is not about overlay. You are getting all items using sax parser this is taking your musch time. Your trying to get all elements and then adding it to map. If you modify your code to as you get an single element update to overlay and populate it may this will fast your execution. If your still suffering from same issue try to add elements using separate thread or canvas object of the overlay (by projection of geo point).

Waylonwayman answered 20/2, 2013 at 11:38 Comment(0)
Z
0

You might want to take a look at implementing a Producer-Consumer model where the consumer will be the map itself and the producer will be the logic that generates information for a pin.

Zetland answered 21/2, 2013 at 11:42 Comment(0)
S
0

You are using a sax parser that's quite time consuming,use a object model representative like a json,that may be easily parsed and so can be plotted on a map.

//Few suggestions that may itself reduce the time problem you are facing.

  1. Only plot the pins and on click open a pop up to display further details inside it.
Soulsearching answered 17/4, 2013 at 7:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.