异步下载图片时,Google Maps集群无法正确绘制

时间:2019-05-20 04:48:37

标签: android-glide android-maps-v2

我正在尝试按照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实例中下载的所有可绘制对象:

enter image description here

这是下载的可绘制位图:

enter image description here

这是结果画布:

enter image description here

我做错了什么?我检查了很多示例,但找不到问题。

0 个答案:

没有答案