I'm using Google Maps Android API Utility Library and I'm downloading certain images from internet that I want to use as markers.
The way I'm doing it is like in the following snippet:
class MarkerItemClusterRenderer extends DefaultClusterRenderer<MarkerItem> {
...
@Override
protected void onBeforeClusterItemRendered(MarkerItem item,
final MarkerOptions markerOptions) {
super.onBeforeClusterItemRendered(item, markerOptions);
mImageLoader.get(item.getImageUrl(), new ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.i("XXX", error.toString());
}
@Override
public void onResponse(ImageContainer response, boolean isImmediate) {
if (response != null && response.getBitmap() != null) {
mImageIcon.setImageBitmap(response.getBitmap());
Bitmap icon = mIconGenerator.makeIcon();
Bitmap bhalfsize = Bitmap.createScaledBitmap(icon, 150,
150, false);
markerOptions.icon(BitmapDescriptorFactory
.fromBitmap(bhalfsize));
}
}
});
}
The problem is, that when the image is downloaded, the map (and thus the marker) doesn't refresh, so most of the times (but not always) I still see the red default markers.
I tried to do mImageIcon.invalidate(); mImageIcon.requestLayout();
but there's still no luck.
Is there anyway to achieve this?
Thanks a lot in advance.
You just need to make all this stuff in
protected void onClusterItemRendered(T clusterItem, Marker marker) {
...
}
In onBeforeClusterItemRendered
you set icon on MarkerOptions
in async callback. At this time it could be added to map and become real Marker
. So you icon will be set to already useless object.
That's why you need to do it in onClusterItemRendered
Let's say you have GoogleMap object declared as:
private GoogleMap mMap;
In onResponse() method before applying any change to marker, try writing following statement to clear previous markers:
mMap.clear();
Now set your new marker.
I might be a bit late but i write it down so it can be useful for somebody looking for a solution like i was.
Basically what you have to do is refresh the marker and not the ClusterItem
, but i used my own ClusterItem
implementation to store some important data.
So your code inside onBeforeClusterItemRendered
becomes like this:
LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; //take visible region on map
if(bounds.contains(item.getPosition()) && !item.hasImage()) { //if item is not inside that region or it has an image already don't load his image
mImageLoader.get(item.getImageUrl(), new ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.i("XXX", error.toString());
}
@Override
public void onResponse(ImageContainer response, boolean isImmediate) {
if (response != null && response.getBitmap() != null) {
mImageIcon.setImageBitmap(response.getBitmap());
Bitmap icon = mIconGenerator.makeIcon();
Bitmap bhalfsize = Bitmap.createScaledBitmap(icon, 150,
150, false);
//Set has image flag
item.setHasImage(true);
//Find the right marker
MarkerManager.Collection markerCollection = mClusterManager.getMarkerCollection();
Collection<Marker> markers = markerCollection.getMarkers();
for (Marker m : markers) {
if (id.equals(m.getTitle())) {
//set the icon
m.setIcon(BitmapDescriptorFactory.fromBitmap(image));
break;
}
}
}
}
});
}
And your MyItem
class must have some parameters which are useful for remember our stuff:
public class MyItem implements ClusterItem {
private String itemId;
private LatLng mPosition;
private WMWall wall;
private boolean hasImage = false;
public MyItem(double latitude, double longitude) {
mPosition = new LatLng(latitude, longitude);
}
@Override
public LatLng getPosition() {
return mPosition;
}
public WMWall getWall() {
return wall;
}
public void setWall(WMWall wall) {
this.wall = wall;
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public boolean hasImage() {
return hasImage;
}
public void setHasImage(boolean hasImage) {
this.hasImage = hasImage;
}
}
It is really important to load only the images of markers contained into bounds, otherwise you'll run into OOM.
And if the hasImage()
method returns true we don't need to load the image again since it is already stored into the marker object.