我正在尝试按照android-map-utils(https://github.com/googlemaps/android-maps-utils)库中的示例实施Google Map集群。区别在于我想从某些URL下载图像。我正在使用Glide库执行此任务。
这是我自定义的ClusterRenderer:
class MapClusterRenderer extends DefaultClusterRenderer<MapClusterItem> {
private static final int MAX_IMAGES_IN_CLUTER = 4;
private static final int MIN_ITEMS_TO_RENDER_AS_CLUSTER = 2;
private Context context;
private int imageDimension;
private IconGenerator itemIconGenerator;
private ImageView itemImageView;
private IconGenerator clusterIconGenerator;
private ImageView clusterImageView;
public MapClusterRenderer(Context context, GoogleMap googleMap, ClusterManager<MapClusterItem> clusterManager) {
super(context, googleMap, clusterManager);
this.context = context;
imageDimension = (int) context.getResources().getDimension(R.dimen.image_xsm);
int padding = (int) context.getResources().getDimension(R.dimen.cluster_marker_padding);
itemImageView = new ImageView(context);
itemImageView.setLayoutParams(new ViewGroup.LayoutParams(imageDimension, imageDimension));
itemImageView.setPadding(padding, padding, padding, padding);
itemIconGenerator = new IconGenerator(context);
itemIconGenerator.setContentView(itemImageView);
View clusterMarkerView = View.inflate(context, R.layout.item_cluster_marker, null);
clusterImageView = clusterMarkerView.findViewById(R.id.images);
clusterIconGenerator = new IconGenerator(context);
clusterIconGenerator.setContentView(clusterMarkerView);
}
@Override
protected void onBeforeClusterItemRendered(MapClusterItem mapClusterItem, MarkerOptions markerOptions) {
markerOptions.visible(false);
}
@Override
protected void onBeforeClusterRendered(Cluster<MapClusterItem> cluster, MarkerOptions markerOptions) {
markerOptions.visible(false);
}
@Override
protected void onClusterItemRendered(MapClusterItem mapClusterItem, Marker marker) {
Glide.with(context)
.load(mapClusterItem.getEstablishment().getImageUrl())
.into(new CustomTarget<Drawable>(imageDimension, imageDimension) {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
itemImageView.setImageDrawable(resource);
Bitmap bitmap = itemIconGenerator.makeIcon();
marker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
marker.setVisible(true);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}
@Override
protected void onClusterRendered(Cluster<MapClusterItem> cluster, Marker marker) {
Thread thread = new Thread(() -> {
List<FutureTarget<Drawable>> futures = new ArrayList<>();
LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder();
for (MapClusterItem mapClusterItem : cluster.getItems()) {
if (futures.size() < MAX_IMAGES_IN_CLUTER) {
FutureTarget<Drawable> future = Glide.with(context)
.load(mapClusterItem.getEstablishment().getImageUrl())
.submit(imageDimension, imageDimension);
futures.add(future);
}
boundsBuilder.include(mapClusterItem.getLatLng());
}
List<Drawable> drawables = new ArrayList<>();
for (FutureTarget<Drawable> future : futures) {
try {
drawables.add(future.get());
} catch (ExecutionException | InterruptedException e) {
Timber.e(e, "Error downloading establishment image. Drawing cluster without this image...");
}
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> {
MultiDrawable multiDrawable = new MultiDrawable(drawables);
multiDrawable.setBounds(0, 0, imageDimension, imageDimension);
clusterImageView.setImageDrawable(multiDrawable);
Bitmap bitmap = clusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
marker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
marker.setPosition(boundsBuilder.build().getCenter());
marker.setVisible(true);
});
});
thread.start();
}
@Override
protected boolean shouldRenderAsCluster(Cluster cluster) {
return cluster.getSize() >= MIN_ITEMS_TO_RENDER_AS_CLUSTER;
}
}
因为我使用的是Glide,所以我需要创建一个后台线程,以使用Glide.submit方法异步下载所有图像,该方法返回一个Future对象。
for (MapClusterItem mapClusterItem : cluster.getItems()) {
if (futures.size() < MAX_IMAGES_IN_CLUTER) {
FutureTarget<Drawable> future = Glide.with(context)
.load(mapClusterItem.getEstablishment().getImageUrl())
.submit(imageDimension, imageDimension);
futures.add(future);
}
boundsBuilder.include(mapClusterItem.getLatLng());
}
然后我等待所有将来的结果,以获取其可绘制对象。
List<Drawable> drawables = new ArrayList<>();
for (FutureTarget<Drawable> future : futures) {
try {
drawables.add(future.get());
} catch (ExecutionException | InterruptedException e) {
Timber.e(e, "Error downloading establishment image. Drawing cluster without this image...");
}
}
不是,我需要像android-map-utils示例一样在UI线程中绘制集群。
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> {
MultiDrawable multiDrawable = new MultiDrawable(drawables);
multiDrawable.setBounds(0, 0, imageDimension, imageDimension);
clusterImageView.setImageDrawable(multiDrawable);
Bitmap bitmap = clusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
marker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
marker.setPosition(boundsBuilder.build().getCenter());
marker.setVisible(true);
});
问题是该代码生成的空白群集标记仅设置了群集大小。
调试此代码后,我看到图像已正确下载,但是调用方法MultiDrawable.draw
时,可绘制对象未正确打印到画布上。
这是在MultiDrawable实例中下载的所有可绘制对象:
这是下载的可绘制位图:
这是结果画布:
我做错了什么?我检查了很多示例,但找不到问题。