Android Google Map clustering not working with data from api

371 Views Asked by At

I have to implement in my app clustering functionality for data loaded from server. I have successfully showed the data in the map using retrofit library, but I tried to do clustering and it is not working. I followed the android docs and some tutorials on internet but I'm very confused of what I'm doing wrong. Here is my code:

Callback<List<Vehicle>> callback = new Callback<List<Vehicle>>() {
            @Override
            public void onResponse(@NotNull Call<List<Vehicle>> call, Response<List<Vehicle>> response) {
                if (response.isSuccessful()) {
                    vehicles = response.body();
                    assert vehicles != null;
                    try {
                        mGoogleMap.clear();
                        for (int i = 0; i < vehicles.size(); i++) {
                            PortalMetaData metaData = vehicles.get(i).getPortalMetaData();
                            float x = metaData.getLocations().getX();
                            float y = metaData.getLocations().getY();

                            float offset = i / 60f;
                            x = x + offset;
                            y = y + offset;

                            MarkerOptions markerOptions = new MarkerOptions();
                            LatLng latLng = new LatLng(x, y);
                            markerOptions.position(latLng);
                            markerOptions.title(metaData.getPortalName());
                            markerOptions.snippet("Id: " + vehicles.get(i).getId());
                            mGoogleMap.addMarker(markerOptions);

                            cameraConfigurations(latLng);

                            mClusterManager = new ClusterManager<>(getApplicationContext(), mGoogleMap);
                            ClusterItem location = new ClusterItem(x, y);

                            mClusterManager.addItem(location);
                            CustomClusterRenderer renderer = new CustomClusterRenderer(getApplicationContext(), mGoogleMap, mClusterManager);
                            //mClusterManager.setAlgorithm(new NonHierarchicalDistanceBasedAlgorithm<>());
                            mClusterManager.setRenderer(renderer);
                            mClusterManager.cluster();

                            mGoogleMap.setOnCameraIdleListener(mClusterManager);
                            mGoogleMap.setOnMarkerClickListener(mClusterManager);
                            mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 5.0f));
                        }
                    } catch (Exception e) {
                        Log.d("onResponse", "There is an error");
                        e.printStackTrace();
                    }

                } else {
                    System.out.println(response.body());
                    Log.e(TAG, "Error: data cannot be loaded");
                }

I'm debugged and everything seems to be fine. and my custom renderer is like that:

private static final int MIN_CLUSTER_SIZE = 1;

    private final IconGenerator mClusterIconGenerator;
    private Context mContext;
    private ClusterManager<ClusterItem> mClusterManager;

    Map<Cluster<ClusterItem>, Marker> clusterMarkerMap = new HashMap<>();

    public CustomClusterRenderer(Context context, GoogleMap map, ClusterManager<ClusterItem> clusterManager) {
        super(context, map, clusterManager);
        mContext = context;
        mClusterManager = clusterManager;
        mClusterIconGenerator = new IconGenerator(context);
    }

    @Override
    protected void onBeforeClusterItemRendered(@NonNull ClusterItem item, @NonNull MarkerOptions markerOptions) {
        BitmapDescriptor mBitmapDescriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA);
        markerOptions.icon(mBitmapDescriptor);
    }

    @Override
    protected void onClusterItemRendered(@NonNull ClusterItem clusterItem, @NonNull Marker marker) {
        super.onClusterItemRendered(clusterItem, marker);
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    @Override
    protected void onBeforeClusterRendered(@NonNull Cluster<ClusterItem> cluster, @NonNull MarkerOptions markerOptions) {
        final Drawable mClusterIcon = mContext.getResources().getDrawable(ic_baseline_directions_car_24);
        mClusterIcon.setColorFilter(mContext.getResources().getColor(android.R.color.holo_orange_light), PorterDuff.Mode.SRC_ATOP);
        mClusterIconGenerator.setBackground(mClusterIcon);
        if (cluster.getSize() > MIN_CLUSTER_SIZE) {
            mClusterIconGenerator.setContentPadding(40, 20, 0, 0);
        } else {
            mClusterIconGenerator.setContentPadding(30, 20, 0, 0);
        }
        Bitmap mIcon = mClusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(mIcon));
    }

    @Override
    protected boolean shouldRenderAsCluster(@NonNull Cluster<ClusterItem> cluster) {
        return cluster.getSize() > MIN_CLUSTER_SIZE;
    }

    @Override
    protected void onClusterRendered(@NonNull Cluster<ClusterItem> cluster, @NonNull Marker marker) {
        super.onClusterRendered(cluster, marker);
        clusterMarkerMap.put(cluster, marker);
    }

Could someone please give me some suggestions of what I'm doing wrong or what could be a good aproach to set clustering correctly.

EDIT: Finally I solved my problem, it was a mistake I was doing. I was adding to cluster manager only one cluster item. I created a new ArrayList of cluster items and in the for loop I added coordinates for each items. Then outside the for loop I called clustermanager.addItems(clusteritems) and is working. Below is my code for anyone facing this issue:

 Callback<List<Vehicle>> callback = new Callback<List<Vehicle>>() {
            @Override
            public void onResponse(@NotNull Call<List<Vehicle>> call, Response<List<Vehicle>> response) {
                if (response.isSuccessful()) {
                    vehicles = response.body();
                    assert vehicles != null;
                    List<ClusterItem> clusterItems = new ArrayList<>();
                    try {
                        mGoogleMap.clear();
                        for (int i = 0; i < vehicles.size(); i++) {
                            PortalMetaData metaData = vehicles.get(i).getPortalMetaData();
                            float x = metaData.getLocations().getX();
                            float y = metaData.getLocations().getY();

                            float offset = i / 60f;
                            x = x + offset;
                            y = y + offset;

                            MarkerOptions markerOptions = new MarkerOptions();
                            LatLng latLng = new LatLng(x, y);
                            markerOptions.position(latLng);
                            markerOptions.title(metaData.getPortalName());
                            markerOptions.snippet("Id: " + vehicles.get(i).getId());
                            mGoogleMap.addMarker(markerOptions);

                            cameraConfigurations(latLng);

                            mClusterManager = new ClusterManager<>(getApplicationContext(), mGoogleMap);
                            ClusterItem location = new ClusterItem(x, y);

                            mClusterManager.addItem(location);
                            clusterItems.add(location);
                            mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 5.0f));
                        }

                        CustomClusterRenderer renderer = new CustomClusterRenderer(getApplicationContext(), mGoogleMap, mClusterManager);
                        mClusterManager.addItems(clusterItems);
                        mClusterManager.setAlgorithm(new NonHierarchicalDistanceBasedAlgorithm<>());
                        mClusterManager.setRenderer(renderer);
                        mClusterManager.cluster();
                        mGoogleMap.setOnCameraIdleListener(mClusterManager);
                        mGoogleMap.setOnMarkerClickListener(mClusterManager);
                    } catch (Exception e) {
                        Log.d("onResponse", "There is an error");
                        e.printStackTrace();
                    }

                } else {
                    System.out.println(response.body());
                    Log.e(TAG, "Error: data cannot be loaded");
                }
0

There are 0 best solutions below