Skip to content

Commit

Permalink
feat: removed render condition
Browse files Browse the repository at this point in the history
  • Loading branch information
kikoso committed Dec 13, 2024
1 parent d3d07d3 commit c6d9482
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ protected void onBeforeClusterRendered(@NonNull Cluster<Person> cluster, @NonNul
}

@Override
protected void onClusterUpdated(@NonNull Cluster<Person> cluster, Marker marker) {
protected void onClusterUpdated(@NonNull Cluster<Person> cluster, @NonNull Marker marker) {
// Same implementation as onBeforeClusterRendered() (to update cached markers)
marker.setIcon(getClusterIcon(cluster));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.util.Log;
import android.util.SparseArray;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
Expand Down Expand Up @@ -92,7 +91,7 @@ public class ClusterRendererMultipleItems<T extends ClusterItem> implements Clus
* Markers that are currently on the map.
*/
private Set<MarkerWithPosition> mMarkers = Collections.newSetFromMap(
new ConcurrentHashMap<MarkerWithPosition, Boolean>());
new ConcurrentHashMap<>());

/**
* Icons for each bucket.
Expand Down Expand Up @@ -147,19 +146,11 @@ public ClusterRendererMultipleItems(Context context, GoogleMap map, ClusterManag

@Override
public void onAdd() {
mClusterManager.getMarkerCollection().setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(@NonNull Marker marker) {
return mItemClickListener != null && mItemClickListener.onClusterItemClick(mMarkerCache.get(marker));
}
});
mClusterManager.getMarkerCollection().setOnMarkerClickListener(marker -> mItemClickListener != null && mItemClickListener.onClusterItemClick(mMarkerCache.get(marker)));

mClusterManager.getMarkerCollection().setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick(@NonNull Marker marker) {
if (mItemInfoWindowClickListener != null) {
mItemInfoWindowClickListener.onClusterItemInfoWindowClick(mMarkerCache.get(marker));
}
mClusterManager.getMarkerCollection().setOnInfoWindowClickListener(marker -> {
if (mItemInfoWindowClickListener != null) {
mItemInfoWindowClickListener.onClusterItemInfoWindowClick(mMarkerCache.get(marker));
}
});

Expand Down Expand Up @@ -350,31 +341,6 @@ protected boolean shouldRenderAsCluster(@NonNull Cluster<T> cluster) {
return cluster.getSize() >= mMinClusterSize;
}

/**
* Determines if the new clusters should be rendered on the map, given the old clusters. This
* method is primarily for optimization of performance, and the default implementation simply
* checks if the new clusters are equal to the old clusters, and if so, it returns false.
* <p>
* However, there are cases where you may want to re-render the clusters even if they didn't
* change. For example, if you want a cluster with one item to render as a cluster above
* a certain zoom level and as a marker below a certain zoom level (even if the contents of the
* clusters themselves did not change). In this case, you could check the zoom level in an
* implementation of this method and if that zoom level threshold is crossed return true, else
* {@code return super.shouldRender(oldClusters, newClusters)}.
* <p>
* Note that always returning true from this method could potentially have negative performance
* implications as clusters will be re-rendered on each pass even if they don't change.
*
* @param oldClusters The clusters from the previous iteration of the clustering algorithm
* @param newClusters The clusters from the current iteration of the clustering algorithm
* @return true if the new clusters should be rendered on the map, and false if they should not. This
* method is primarily for optimization of performance, and the default implementation simply
* checks if the new clusters are equal to the old clusters, and if so, it returns false.
*/
protected boolean shouldRender(@NonNull Set<? extends Cluster<T>> oldClusters, @NonNull Set<? extends Cluster<T>> newClusters) {
return true;
}

/**
* Transforms the current view (represented by DefaultClusterRenderer.mClusters and DefaultClusterRenderer.mZoom) to a
* new zoom level and set of clusters.
Expand Down Expand Up @@ -424,10 +390,6 @@ public void setMapZoom(float zoom) {

@SuppressLint("NewApi")
public void run() {
if (!shouldRender(immutableOf(ClusterRendererMultipleItems.this.mClusters), immutableOf(clusters))) {
mCallback.run();
return;
}

final MarkerModifier markerModifier = new MarkerModifier();

Expand Down Expand Up @@ -578,10 +540,6 @@ public void setAnimationDuration(long animationDurationMs) {
mAnimationDurationMs = animationDurationMs;
}

private Set<? extends Cluster<T>> immutableOf(Set<? extends Cluster<T>> clusters) {
return clusters != null ? Collections.unmodifiableSet(clusters) : Collections.emptySet();
}

private static double distanceSquared(Point a, Point b) {
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.maps.android.clustering;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

import android.content.Context;

import com.google.android.gms.maps.GoogleMap;
import com.google.maps.android.clustering.algo.Algorithm;
import com.google.maps.android.collections.MarkerManager;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import java.util.Arrays;
import java.util.Collection;

public class ClusterManagerTest<T extends ClusterItem> {

private ClusterManager<T> classUnderTest;
private Algorithm<T> algorithm;

private Context mockContext;
private GoogleMap mockMap;
private MarkerManager mockMarkerManager;

@Before
public void setUp() {
// Create mocks for dependencies
mockContext = mock(Context.class);
mockMap = mock(GoogleMap.class);
mockMarkerManager = mock(MarkerManager.class);
algorithm = mock(Algorithm.class);

// Initialize the class under test with the mocked dependencies
classUnderTest = new ClusterManager<T>(mockContext, mockMap, mockMarkerManager) {
@Override
public Algorithm<T> getAlgorithm() {
return algorithm;
}
};
}

@Test
public void testDiff() {
// Use a specific class type for T
Class<T> type = (Class) String.class; // Replace with actual type
algorithm = mock(Algorithm.class);

classUnderTest = spy(new ClusterManager<T>(mock(Context.class), mock(GoogleMap.class), mock(MarkerManager.class)) {
@Override
public Algorithm<T> getAlgorithm() {
return algorithm;
}
});

// Mock input collections using the explicit type
T addItem1 = mock(type);
T addItem2 = mock(type);
Collection<T> add = Arrays.asList(addItem1, addItem2);

T removeItem = mock(type);
Collection<T> remove = Arrays.asList(removeItem);

T modifyItem1 = mock(type);
T modifyItem2 = mock(type);
T modifyItem3 = mock(type);
Collection<T> modify = Arrays.asList(modifyItem1, modifyItem2, modifyItem3);

// Call the method under test
classUnderTest.diff(add, remove, modify);

// Verify algorithm lock and unlock
verify(algorithm).lock();
verify(algorithm).unlock();

// Verify add items
for (T item : add) {
verify(algorithm).addItem(item);
}

// Verify remove items
verify(algorithm).removeItems(remove);

// Verify modify items
for (T item : modify) {
verify(classUnderTest).updateItem(item);
}
}

@Test
public void testDiffWithNullCollections() {
// Call the method with null collections
classUnderTest.diff(null, null, null);

// Verify locking and unlocking
verify(algorithm).lock();
verify(algorithm).unlock();

// Verify no operations are called
verifyNoMoreInteractions(algorithm);
}
}

0 comments on commit c6d9482

Please sign in to comment.