Skip to content

removeFeature() silently fails for MultiGeometry features (objects stranded on map, duplicated on re-add) #1722

Description

@jamesarich

Summary

MapViewRenderer.removeFeature(feature) is a no-op for any feature whose geometry is a MultiGeometry (GeoJSON MultiPolygon / MultiLineString / MultiPoint / GeometryCollection, KML MultiGeometry). The rendered polygons/polylines/markers stay on the map forever, and adding the feature again duplicates them. removeLayer() is affected the same way since it delegates to removeFeature per feature.

Expected behavior

removeFeature(feature) removes every map object that addFeature(feature) created, for any geometry type.

Observed behavior

For MultiGeometry features nothing is removed. Root cause: addFeature renders the members by recursing with addFeature(feature.copy(geometry = member)), so the created map objects are recorded in the renderedFeatures IdentityHashMap under those intermediate copies. The original feature never gets an entry (mapObjects stays empty at the outer level), so removeFeature(originalFeature) finds nothing.

This also breaks the deprecated GeoJsonLayer/KmlLayer bridges: removeLayerFromMap() leaves all multi-geometry features on the map, and a subsequent addLayerToMap() duplicates them — i.e. layer visibility toggling is broken for any file containing a MultiPolygon.

Environment details

  1. Any (found via unit test + code inspection; hit in production via maps-compose 8.4.0 → maps-utils-ktx 6.2.0 → android-maps-utils 5.0.0)
  2. Any
  3. android-maps-utils 5.0.0 (data module, introduced by the v5 rewrite feat!: rewrite android maps utils #1658)

Steps to reproduce

val renderer = MapViewRenderer(map, UrlIconProvider())
val feature = Feature(
    geometry = MultiGeometry(
        listOf(
            Polygon(listOf(Point(0.0, 0.0), Point(0.0, 1.0), Point(1.0, 1.0))),
            Polygon(listOf(Point(2.0, 2.0), Point(2.0, 3.0), Point(3.0, 3.0))),
        ),
    ),
)
renderer.addFeature(feature)
renderer.removeFeature(feature) // <- removes nothing; both polygons remain on the map

Or with the deprecated API: load any GeoJSON containing a MultiPolygon into GeoJsonLayer, call addLayerToMap(), then removeLayerFromMap() — the polygons remain.

I have a fix ready (render nested geometries into the original feature's renderedFeatures entry instead of recursing with copies) with regression tests — PR incoming.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions