1

I was wondering what is the proper way of loading ItemizedOverlay markers from the web, use caching in some sort of a way.

Right now i'm downloading all the images and converting them to drawables, it works just fine but I want to see if there is a better way of doing this.

public class ImageLoad extends AsyncTask<String, Bitmap, Bitmap> {
private String url;
private MapView mapView;

public ImageLoad() {
}

public ImageLoad(MapView mapView) {
    this.mapView = mapView;
}

protected Bitmap doInBackground(String... params) {
    url = params[0];
    try {
        return BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream());
    } catch (MalformedURLException e) {
        e.printStackTrace();
        return null;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

@Override
protected void onPostExecute(Bitmap result) {
    Drawable d = new BitmapDrawable(mapView.getContext().getResources(), result);
    SimpleItemizedOverlay itemizedOverlay = new SimpleItemizedOverlay(d, mapView);
    GeoPoint p = new GeoPoint(32061628, 34774767);
    itemizedOverlay.addOverlay(new OverlayItem(p, "zzz", "zzz"));
    mapView.getOverlays().add(itemizedOverlay);
    mapView.invalidate();
    super.onPostExecute(result);
}
}
meh
  • 22,090
  • 8
  • 48
  • 58

3 Answers3

1

I would suggest you use a default image as a overlay drawable while the lazyLoader downloads the images, puts them in the chache (two level cache: in memory and on the disk) and notifies the overlay when the image is ready who then refreshes it's view.

whlk
  • 15,487
  • 13
  • 66
  • 96
  • I was thinking about loading all the images first, and only then displaying all the overlays. Is there anyway to change the drawable of the itemized overlay after it was added to the map? – meh Nov 05 '12 at 14:52
  • I think you are on the right track. getOverlays also lets you access the overlays list and change them. public final java.util.List getOverlays() With this, you can do things like remove and readd overlay items. – Joe Plante Nov 09 '12 at 20:23
1

The overall approach is correct, but the details how you implemented it can be improved.

Improvement 1

In your onPostExecute() every time you download an image you are creating a new ItemizedOverlay object and add a single item to it. In general, is more efficient to use a unique ItemizedOverlay and add all the items to it.

  • Create ItemizedOverlay and add it to MapView.getOverlays().add() before load first image
  • Change ImageLoad class to receive ItemizedOverlay instead of MapView
  • In onPostExecute() create a new OverlayItem and add it to ItemizedOverlay

With this, you will have only one ItemizedOverlay with several items in it. With your code you have several ItemizedOverlays with one image each.

Improvement 2

You are not resizing the images that you download the Web. Unless you are sure they all have a suitable size, you should enforce the size before add them to the overlay. Otherwise, you will be using more memory and could get an image that covers all the screen and thats not what user expects.

You can resize the Bitmap using method Bitmap.createScaledBitmap().

Regards.

Luis
  • 11,978
  • 3
  • 27
  • 35
  • So I need to download first the image, fill the itemizedoverlay and then return it, and if it is not empty add it to the overlays list? – meh Nov 13 '12 at 11:21
  • No. You can add the itemizedOverlay to the overlay list before starting downloading images, even if it's empty. This should be done just once, not every time you download one additional image. Alternativly, you could add it only after you add the first image, but never again. New images would be added to the already existing ItemizedOverlay. I´ve edited my answer to make it a litle more clear. – Luis Nov 13 '12 at 11:43
  • You need to call `populate()` on `itemizedOverlay` before you use it, even if it's empty. This solve the problem of null pointer. Anyway, you can add it just after you add the first item (method where you are probably calling the populate) as I said above. – Luis Nov 13 '12 at 12:20
  • Each itemizedoverlay has only one image(drawable) instance for the marker, I can't change the marker after it has already been added, am I right? or can I set the marker after the itemizedoverlay has been initiated already? – meh Nov 13 '12 at 12:23
  • The image that you assign to the Itemized overlay is the default image, and as far as I know, you can't (or you shouldn't) change it. However, the object ´OverlayItem` that you add to the `ItemizedOverlay` can have is own image assigned (if no image is assigned to it, the default from `ItemizedOverlay` is used) using the method `setMarker()`. So, after you download the image, you create the `OverlayItem`, use `setMarker()` to assign the image to the item, and then add the item to the ´ItemizedOverlay`. – Luis Nov 13 '12 at 12:40
  • I see now, I will just fill the overlays when the image finishes to download and call 'set marker' on each overlay item since each overlay in a single itemizedoverlay has the same marker, but what if I have like 50-60 overlays wouldn't it consume too much time, or probably not if i'm doing it in a different thread. I will definitely try that, thank you. And I want to have different itemizedoverlays, it is on purpose. – meh Nov 13 '12 at 13:00
  • I've already use several hundreds of markers in one `ItemizedOverlay` and it worked smoothly (althought all makers were the same default image). Just be careful with the subject i refer in `Improvment 2` as big images will exhaust quickly available memory, as well as, more time is required to have them redrawn on the screen. – Luis Nov 13 '12 at 13:43
0

you can try this way....see the link..this is the demo of lazy loading images so, here first time images downloading and store its cache in sdcard. so, everytime it does not take more time to loading markers from web.

http://developand.blogspot.in/2010/11/lazy-loading.html

Mehul Ranpara
  • 4,245
  • 2
  • 26
  • 39