4

I have a map view with thousand of items that i want to load on it. obviously i can't load them all when the view is created.

I guess that I have to load them asynchronously according to what is currently displayed..

How can I load only items located in the map portion displayed on the screen?

Matteo
  • 276
  • 1
  • 4
  • 18

1 Answers1

8

Use AsyncTask to load the individual layers per screen. Get the Lat/Long of the currently visible map using MapView api. On the backend send them the lat/long bounding box to get the items you want. So roughly from memory it would be something like:

public class LoadMapItems extends AsyncTask<Integer,Integer,List<ItemizedOverlay>> {
   private MapView view;

   public LoadMapItems( MapView view ) {
      this.view = view;
   }

   public List<ItemizedOverlay> doInBackground( Integer... params ) {
      int left = params[0];
      int top = params[1];
      int right = params[2];
      int bottom = params[3];

      return convertToItemizedOverlay( someService.loadSomething( left, top, right, bottom ) );
   } 

   private List<ItemizedOverlay> convertToItemizedOverlay( List<SomeObject> objects ) {
      // ... fill this out to convert your back end object to overlay items
   }

   public void onPostExecute(List<ItemizedOverlay> items) {
      List<Overlay> mapOverlays = mapView.getOverlays();
      for( ItemizedOverlay item : items ) {
         mapOverlays.add( item );
      }
   }
}

// somewhere else in your code you do this:

GeoPoint center = someMap.getMapCenter();
new LoadMapItems( someMap ).execute( 
      center.getLongitude() - someMap.getLongitudeSpan() / 2,
      center.getLatitude() - someMap.getLatitudeSpan() / 2,
      center.getLongitude() + someMap.getLongitudeSpan() / 2,
      center.getLatitude() + someMap.getLatitudeSpan() / 2);
chubbsondubs
  • 37,646
  • 24
  • 106
  • 138
  • Thanks! this is very helpful. But how can I handle a change on the currently visible map? – Matteo Apr 05 '11 at 11:18
  • Your MapView will dispatch events when someone moves it around. During that event handler you'll use this AsyncTask to load the data from your backend service. I'd get that working then once it's working I'd consider caching those loads in a data structure possibly Map>. It gets a little tricker, but it could make it much faster. Then you'd check that data structure when the user drags the map to see if you've already loaded that tile... – chubbsondubs Apr 06 '11 at 02:44
  • ...In fact you might find it easier to assign your overlays to a fixed grid cell and load those grid cells that intersect with your MapView's current lat/long span as I illustrated. That makes it easier to cache the fixed grid segments. You might load features that exist outside the viewable area, but it will be small. The max number of grid cells you load would be 4. Plus it's easier to optimize on the backend because your database can index on a fixed key. You just need to convert a lat/long into a grid cell number and load the features assigned to that grid cell number. – chubbsondubs Apr 06 '11 at 02:49