[google_maps_flutter_android] Reindex clustered markers in spatial index on position change#11749
[google_maps_flutter_android] Reindex clustered markers in spatial index on position change#11749EverCamilo wants to merge 3 commits into
Conversation
…dex on position change When a clustered marker position is updated in-place via MarkersController.changeMarkers(), the ClusterManager NonHierarchicalDistanceBasedAlgorithm retains stale QuadTree entries at the old coordinates. This causes ghost clusters to appear at positions where no marker currently exists. Fix: capture the marker position before interpretMarkerOptions(), compare after, and if changed call removeItem + addItem on the ClusterManager to refresh the QuadTree. Batch variant added for the public changeMarkers() path for efficiency. Co-authored-by: Cursor <cursoragent@cursor.com>
|
It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
There was a problem hiding this comment.
Code Review
This pull request introduces reindexing logic to handle in-place position updates for clustered markers by adding reindexItem and reindexItems methods to ClusterManagersController. However, the review feedback indicates a logic error where marker positions are updated before the removal from the spatial index is triggered. This prevents the ClusterManager from correctly locating and removing markers from their old coordinates in the QuadTree, which would result in the failure to clear stale data.
| public void reindexItem(@NonNull String clusterManagerId, @NonNull MarkerBuilder item) { | ||
| ClusterManager<MarkerBuilder> clusterManager = clusterManagerIdToManager.get(clusterManagerId); | ||
| if (clusterManager != null) { | ||
| clusterManager.removeItem(item); |
There was a problem hiding this comment.
The reindexItem method (and reindexItems below) will fail to remove the item from the spatial index if its position has already been updated. The ClusterManager.removeItem method relies on the item's current getPosition() to locate it in the underlying QuadTree. If the position was mutated before calling this method, the removal will look at the new coordinates, while the item is still indexed at the old coordinates, leading to the "ghost clusters" this PR intends to fix.
| if (clusterManagerId != null && !markerBuilder.getPosition().equals(oldPosition)) { | ||
| markersToReindexByCluster | ||
| .computeIfAbsent(clusterManagerId, k -> new ArrayList<>()) | ||
| .add(markerBuilder); | ||
| } |
There was a problem hiding this comment.
In changeMarkers, interpretMarkerOptions is called at line 140, which updates the markerBuilder's position. The subsequent call to reindexItems (line 168) will attempt to remove the markers using their new positions. This will fail to clear the old entries from the ClusterManager's spatial index. To fix this, markers whose positions are changing should be removed from the ClusterManager before their state is mutated, or the reindexing logic must be provided with the old coordinates to perform the removal.
| if (clusterManagerId != null && !markerBuilder.getPosition().equals(oldPosition)) { | ||
| clusterManagersController.reindexItem(clusterManagerId, markerBuilder); | ||
| } |
There was a problem hiding this comment.
Similar to the batch update path, in changeMarker, the markerBuilder is updated at line 397 before reindexItem is called. This prevents the ClusterManager from correctly identifying and removing the marker from its old position in the spatial index because removeItem will be searching at the new coordinates.
The QuadTree locates entries by getPosition(). The previous reindexItem approach called removeItem after the position was already mutated, so the spatial lookup searched at the new coordinates and missed the stale entry at the old position. Fix: call removeItemSilently (without recluster) BEFORE interpretMarkerOptions mutates the builder, then batch re-add after mutation. This ensures the QuadTree removal finds the item at its original coordinates. Co-authored-by: Cursor <cursoragent@cursor.com>
The previous commit removed and re-added ALL clustered markers unconditionally, causing excessive cluster() calls that could interfere with tap detection. Now we only reindex markers whose position actually changed. To correctly remove the stale QuadTree entry (which requires the old position), the builder is temporarily set back to the old coordinates for removal, then restored to the new coordinates for re-addition. Co-authored-by: Cursor <cursoragent@cursor.com>
Description
When a clustered marker's position is updated in-place via \MarkersController.changeMarkers(), the \ClusterManager's \NonHierarchicalDistanceBasedAlgorithm\ retains stale \QuadTree\ entries at the old coordinates. This causes ghost clusters to appear at positions where no marker currently exists.
Root cause
\MarkersController.changeMarkers()\ has two code paths when updating a marker:
emoveItem\ + \�ddItem\ on the \ClusterManager, refreshing the spatial index.
Fix
emoveItem\ + \�ddItem\ to refresh the \QuadTree.
eindexItems) added for the public \changeMarkers()\ path — calls \cluster()\ only once per \ClusterManager\ for efficiency.
Files changed
eindexItem()\ and
eindexItems()\ methods.
Reproduction
Pre-launch Checklist