Android-maps-utils: Glide not renders images to markers in clusters when on first time map loaded. It loads images after once zoom in and zoom out the map

Created on 24 Aug 2017  路  9Comments  路  Source: googlemaps/android-maps-utils

I am using cluster in my map and created custom markers with images and using glide to download images from url and render it to my markers. But what my problem is on first time when my map loaded images are are not rendered to markers. After some zoom in zoom out the map only the glide start to download the images. But I want to download images at first call of map loading.If i use URL stream download it works fine. But that will download every time the images. Anybody please help me to resolve this problem. Here after I have attached my code.

import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.maps.android.clustering.Cluster;
import com.google.maps.android.clustering.ClusterItem;
import com.google.maps.android.clustering.ClusterManager;
import com.google.maps.android.clustering.view.DefaultClusterRenderer;
import com.google.maps.android.ui.IconGenerator;
import com.google.maps.android.utils.demo.model.Person;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Demonstrates heavy customisation of the look of rendered clusters.
 */
public class CustomMarkerClusteringDemoActivity2 extends FragmentActivity implements OnMapReadyCallback,ClusterManager.OnClusterClickListener<Person>, ClusterManager.OnClusterInfoWindowClickListener<Person>, ClusterManager.OnClusterItemClickListener<Person>, ClusterManager.OnClusterItemInfoWindowClickListener<Person> {
    private ClusterManager<Person> mClusterManager;
    private Random mRandom = new Random(1984);


    private GoogleMap mMap;

    protected int getLayoutId() {
        return R.layout.map;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
        setUpMap();
    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMap();
    }

    @Override
    public void onMapReady(GoogleMap map) {
        if (mMap != null) {
            return;
        }
        mMap = map;
        startDemo();
    }

    private void setUpMap() {
        ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMapAsync(this);
    }

    protected GoogleMap getMap() {
        return mMap;
    }

    /**
     * Draws profile photos inside markers (using IconGenerator).
     * When there are multiple people in the cluster, draw multiple photos (using MultiDrawable).
     */
    private class PersonRenderer extends DefaultClusterRenderer<Person> {
        private final IconGenerator mIconGenerator = new IconGenerator(getApplicationContext());
        private final IconGenerator mClusterIconGenerator = new IconGenerator(getApplicationContext());
        private final ImageView mImageView;
        private final ImageView mClusterImageView;
        private final int mDimension;

        public PersonRenderer() {
            super(getApplicationContext(), getMap(), mClusterManager);

            View multiProfile = getLayoutInflater().inflate(R.layout.multi_profile, null);
            mClusterIconGenerator.setContentView(multiProfile);
            mClusterImageView = (ImageView) multiProfile.findViewById(R.id.image);

            mImageView = new ImageView(getApplicationContext());
            mDimension = (int) getResources().getDimension(R.dimen.custom_profile_image);
            mImageView.setLayoutParams(new ViewGroup.LayoutParams(mDimension, mDimension));
            int padding = (int) getResources().getDimension(R.dimen.custom_profile_padding);
            mImageView.setPadding(padding, padding, padding, padding);
            mIconGenerator.setContentView(mImageView);
        }

        @Override
        protected void onBeforeClusterItemRendered(Person person, MarkerOptions markerOptions) {
            Glide.with(CustomMarkerClusteringDemoActivity2.this)
                    .load(person.profilePhoto).asBitmap()
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .fitCenter()
                    .placeholder(R.drawable.ic_launcher).dontAnimate().into(mImageView);

            //            URL url = null;
//            try {
//                url = new URL(person.profilePhoto);
//                Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
//                mImageView.setImageBitmap(bmp);
//            } catch (MalformedURLException e) {
//                e.printStackTrace();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }

            Bitmap icon = mIconGenerator.makeIcon();
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon)).title(person.name);
        }

        @Override
        protected void onBeforeClusterRendered(Cluster<Person> cluster, MarkerOptions markerOptions) {
            // Draw multiple people.
            // Note: this method runs on the UI thread. Don't spend too much time in here (like in this example).
            List<Drawable> profilePhotos = new ArrayList<Drawable>(Math.min(4, cluster.getSize()));
            int width = mDimension;
            int height = mDimension;
            Bitmap dummyBitmap=null;
            Drawable drawable=null;

            for (Person p : cluster.getItems()) {
                // Draw 4 at most.
                if (profilePhotos.size() == 4) break;
                try {

                    dummyBitmap = Glide.with(getApplicationContext()).load(p.profilePhoto)
                            .asBitmap().into(70,70).get();

                } catch (Exception e) {
                    e.printStackTrace();
                }
                drawable = new BitmapDrawable(getResources(), dummyBitmap);
                drawable.setBounds(0, 0, width, height);
                profilePhotos.add(drawable);
            }

            MultiDrawable multiDrawable = new MultiDrawable(profilePhotos);
            multiDrawable.setBounds(0, 0, width, height);

            mClusterImageView.setImageDrawable(multiDrawable);
            Bitmap icon = mClusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
        }

        @Override
        protected boolean shouldRenderAsCluster(Cluster cluster) {
            // Always render clusters.
            return cluster.getSize() > 1;
        }
    }

    @Override
    public boolean onClusterClick(Cluster<Person> cluster) {
        // Show a toast with some info when the cluster is clicked.
        String firstName = cluster.getItems().iterator().next().name;
        Toast.makeText(this, cluster.getSize() + " (including " + firstName + ")", Toast.LENGTH_SHORT).show();

        // Zoom in the cluster. Need to create LatLngBounds and including all the cluster items
        // inside of bounds, then animate to center of the bounds.

        // Create the builder to collect all essential cluster items for the bounds.
        LatLngBounds.Builder builder = LatLngBounds.builder();
        for (ClusterItem item : cluster.getItems()) {
            builder.include(item.getPosition());
        }
        // Get the LatLngBounds
        final LatLngBounds bounds = builder.build();

        // Animate camera to the bounds
        try {
            getMap().animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }

    @Override
    public void onClusterInfoWindowClick(Cluster<Person> cluster) {
        // Does nothing, but you could go to a list of the users.
    }

    @Override
    public boolean onClusterItemClick(Person item) {
        // Does nothing, but you could go into the user's profile page, for example.
        return false;
    }

    @Override
    public void onClusterItemInfoWindowClick(Person item) {
        // Does nothing, but you could go into the user's profile page, for example.
    }

    protected void startDemo() {
        getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(9.9252,78.1198), 8f));

        mClusterManager = new ClusterManager<Person>(this, getMap());
        mClusterManager.setRenderer(new PersonRenderer());
        getMap().setOnCameraIdleListener(mClusterManager);
        getMap().setOnMarkerClickListener(mClusterManager);
        getMap().setOnInfoWindowClickListener(mClusterManager);
        mClusterManager.setOnClusterClickListener(this);
        mClusterManager.setOnClusterInfoWindowClickListener(this);
        mClusterManager.setOnClusterItemClickListener(this);
        mClusterManager.setOnClusterItemInfoWindowClickListener(this);

        addItems();
        mClusterManager.cluster();
    }

    private void addItems() {
        mClusterManager.addItem(new Person(new LatLng(9.9252,78.1198), "Madurai",  "https://images.techhive.com/images/article/2016/09/android-old-habits-100682662-primary.idge.jpg"));

        mClusterManager.addItem(new Person(new LatLng(13.0827,80.2707), "Chennai", "https://images.techhive.com/images/article/2016/09/android-old-habits-100682662-primary.idge.jpg"));

        mClusterManager.addItem(new Person(new LatLng(10.9675,76.9182), "Covai", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSppY02DkBSDtdnf8EVLKm7-n_0AlO1v5NKCcMWeVdzZ0VkIIiECA"));

        mClusterManager.addItem(new Person(new LatLng(10.7905,78.7047), "Trichy", "http://4.bp.blogspot.com/-8v_k_fOcfP8/UQIL4ufghBI/AAAAAAAAEDo/9ffRRTM9AnA/s1600/android-robog-alone.png"));

        mClusterManager.addItem(new Person(new LatLng(10.3673,77.9803), "Dindigul", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRArxJKW72owkwK0zD60Q_GJiVg36vy80Xf1dBPGBk87AefQa5e"));

//        mClusterManager.addItem(new Person(position(), "Yeats", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3Ab0euUF-ClwheIfODe04krTeGIkD-wf-gYQcaZWhAHzD4nOp"));
//
//        mClusterManager.addItem(new Person(position(), "John", "http://www.jrtstudio.com/sites/default/files/ico_android.png"));
//
//        mClusterManager.addItem(new Person(position(), "Trevor the Turtle", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQmVSoCOR98Vw7iqlm-LWjZ_iTt5ZhvMy8TqUb7zyKNj4VoSWhZ"));
//
//        mClusterManager.addItem(new Person(position(), "Teach1", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRuYdYnhMjcvd4hAH3-5hvPavCgb3b_8Rs6UTtviCoOTpIEwvig"));
//
//        mClusterManager.addItem(new Person(position(), "Teach2", "http://www.lyps.edu.hk/wp-content/uploads/2014/08/unnamed.png"));
//
//        mClusterManager.addItem(new Person(position(), "Teach3", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTVdtXystrbg1tU-WzII4Tbp7oWBgDZ_RmDVpCxTgwGyEEOrh6bxg"));
//
//        mClusterManager.addItem(new Person(position(), "Teach4", "https://lh4.ggpht.com/KZpaG6K6Q7JV9CqN7uKfapGwZoK3PLEeZYbALpMO1sY4jJ4FPbYY12Uu-wY2vO9xXZE=w300"));
//
//        mClusterManager.addItem(new Person(position(), "Teach5", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTDmE3crCrCt4lnMZPzaPLna3xRZwCG-x1_adS98fRebfU_aYlZXg"));
//
//        mClusterManager.addItem(new Person(position(), "Teach6", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRiMaki37C4rnhvKOUXyuIGuDxm-sfNiC-jkqU9WkXx-yj8PvqDvw"));
//
//        mClusterManager.addItem(new Person(position(), "Teach7", "https://lh3.ggpht.com/wFQnMKpl6M1JGhG2nfGY5WGiZqWBkKTsGkFLngwQxjKbEBN6bpAh3ljUu3KQVozH0sI=w300"));
//
//        mClusterManager.addItem(new Person(position(), "Teach8", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTodrOHInZLLQmkA9H_0OBg472_OROG47GoEB53HFi5O3fZYmi7bA"));
    }

    private LatLng position() {
        return new LatLng(random(51.6723432, 51.38494009999999), random(0.148271, -0.3514683));
    }

    private double random(double min, double max) {
        return mRandom.nextDouble() * (max - min) + min;
    }
}

Thanks in advance...

duplicate

All 9 comments

No idea?

same problem...

Same Problem...

Same problem

@satheesh1000 Find any solution ??

Same Problem

i figured out this problem with override onClusterRendered not override onBeforeClusterRendered
but i have a problem that the number of cluster items differs from the number shown on the map.

Hello,

I am having the same issue, could you please share your fix for getting the images to display? It also appears that the cluster number is differing because it adds the same markers so everything is doubled.

Thank you for reporting. This is a duplicate issue as the one described in #90.

Essentially, updating the marker icon once an initial one has been set (synchronously) in onBeforeClusterItemRendered is not currently possible. You can follow the discussion in #90 for a possible workaround.

In the case of Glide/Picasso/Fresco/etc., you would have to prefetch the marker images and cache them locally. Once that's completed, only then can you add each individual item followed by invoking cluster().

Was this page helpful?
0 / 5 - 0 ratings

Related issues

WeiLinJoe picture WeiLinJoe  路  4Comments

vardaan picture vardaan  路  6Comments

bedzinsa picture bedzinsa  路  7Comments

air89 picture air89  路  6Comments

Slake07 picture Slake07  路  3Comments