Reputation: 4617
I have one problem.
My goal is to load custom image of company and show it instead default marker icon.
But I have faced with the problem.
Icons are shown only if I close and open activity again.
Here is my code for adding markers to the map.
private void addMarkerToTheMap(GoogleMapInfoBundle infoBundle) {
if (infoBundle.placeMarker) {
LatLng latLng = new LatLng(infoBundle.company.getLatitude(), infoBundle.firm.getLongitude());
MarkerOptions markerOptions = new MarkerOptions()
.title(infoBundle.company.getName())
.snippet(infoBundle.company.getAddress())
.position(latLng);
Marker marker = mGoogleMap.addMarker(markerOptions);
try {
Picasso.with(this).load(NetworkUtils.getUrlOfScaledImage(infoBundle.company.getLogo(), DEFAULT_ICON_SCALE_PERCENTAGE)).into(new PicassoMarker(marker));
} catch (IllegalArgumentException ignore) {
// Do nothing
}
}
And PicassoMarker
public class PicassoMarker implements Target {
Marker mMarker;
public PicassoMarker(Marker marker) {
mMarker = marker;
}
@Override
public int hashCode() {
return mMarker.hashCode();
}
@Override
public boolean equals(Object o) {
if (o instanceof PicassoMarker) {
Marker marker = ((PicassoMarker) o).mMarker;
return mMarker.equals(marker);
} else {
return false;
}
}
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
mMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
}
In this case it displays default icon .
I have tried to make it in another way like this
MarkerOptions markerOptions = new MarkerOptions()
.title(infoBundle.company.getName())
.snippet(infoBundle.company.getAddress())
.position(latLng);
try {
Picasso.with(this).load(NetworkUtils.getUrlOfScaledImage(infoBundle.company.getLogo(), DEFAULT_ICON_SCALE_PERCENTAGE)).into(new PicassoMarker(mGoogleMap, markerOptions));
} catch (IllegalArgumentException ignore) {
// Do nothing
}
And add marker to the map in callback after image has been downloaded.
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
mMarkerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
mGoogleMap.addMarker(mMarkerOptions);
}
It doesn't show any marker in this case.
But in both cases if I close Activity
and open it again everything will be displayed correctly with icons as it should.
I have no idea what can cause such problem. It seems GoogleMap
caches icon image or something else.
I have a little experience working with GoogleMaps API
, maybe I am missing something.
Hope someone can help.
Thanks.
Upvotes: 1
Views: 2383
Reputation: 4617
The problem was not in GoogleMap
or SupportMapFragment
it was in Picasso
, not exactly in Picasso
but in my flow.
The thing you should always remember using custom Target
classes is that internally Picasso
uses WeakReference
for storing Target
objects, so if you will just create new Target
directly inside Picasso
call it will be destroyed by garbage collector.
Picasso
provides Callback
class, so you can create anonymous class instead and that you class will hold the reference.
But one thing that is I am missing Callback
class that provides Bitmap
in response like Target
(but targets are mostly used by custom views).
So I have found such solution, it ugly, but here it is.
I have created special list for storing target objects, not to be garbaged.
Marker marker = mGoogleMap.addMarker(markerOptions);
mMarkerCompanyMap.put(marker, infoBundle.firm);
try {
PicassoMarkerTarget markerTarget = new PicassoMarkerTarget(marker, mImageLoadingCallback);
mPicassoMarkerTargetList.add(markerTarget);
Picasso.with(this)
.load(NetworkUtils.getUrlOfScaledImage(infoBundle.firm.getLogo(), DEFAULT_ICON_SCALE_PERCENTAGE))
.into(markerTarget);
} catch (IllegalArgumentException ignore) {
// Do nothing
}
I am passing mImageLoadingCallback
for having callback back to the activity from Target
And it looks like.
private Callback mImageLoadingCallback = new Callback() {
@Override
public void onSuccess() {
Logger.logError("IMAGE LOADED IN CALLBACK " + mPendingImagesCount);
if (mPendingImagesCount <= 0) {
mPicassoMarkerTargetList.clear();
} else {
mPendingImagesCount--;
}
}
@Override
public void onError() {
// You may start laughing, but just for the sake of not duplicating code
onSuccess();
}
};
This callback can be used for other purposes, but now only for clear array.
And of course PicassoMarkerTarget
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
mMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
mDownloadListenerCallback.onSuccess();
Logger.logError("IMAGE LOADED IN PICASSO MARKER TARGET");
}
This is ugly solution but maybe this callback can be helpful in the future.
Please, if you have idea how to make solution better - please share it. Thanks.
Upvotes: 1