From 2da6be659036def75e0c9d853419f635d324d805 Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Sat, 7 Nov 2026 13:16:50 -0800 Subject: [PATCH 1/3] Take the MapView off the lifecycle and destroy it when the map leaves registerLifecycle() adds the MapView to the Activity's lifecycle and the SDK's onDestroy() does not remove it, so the Activity kept every map the user switched away from. It is now removed from the lifecycle, paused and destroyed through MapViewBase's onDestroyMapView, once. --- .../openmobilemaps/OpenMobileMapsMapView.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt index f2ae8f9..ec26c87 100644 --- a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt +++ b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt @@ -280,6 +280,16 @@ fun OpenMobileMapsMapView( }, style = style, onStyleDiagnostics = onStyleDiagnostics, + // registerLifecycle() put the MapView on the Activity's lifecycle, and + // its own onDestroy() does not take it off again: left there, the + // Activity keeps every map the user switched away from (and through + // its callbacks the controller with every overlay). Take it off first + // so the Activity's ON_DESTROY cannot destroy it a second time. + onDestroyMapView = { surface -> + lifecycleOwner.lifecycle.removeObserver(surface.mapView) + surface.mapView.onPause() + surface.mapView.onDestroy() + }, content = content, ) } From fd9f41fa53e1f713c4d8fa67ce8402d763ef1660 Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Sat, 7 Nov 2026 15:19:03 -0800 Subject: [PATCH 2/3] Remove the touch listener when the controller is destroyed The touch handler holds the listener through a JNI global reference, so every controller (with its overlays) stayed in the process after its map was gone. --- .../OpenMobileMapsMapViewController.kt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt index 05e3ee1..f00455d 100644 --- a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt +++ b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt @@ -166,9 +166,17 @@ class OpenMobileMapsMapViewController( } } + /** + * 地図に挿したタッチリスナー。SDK はネイティブ側から JNI の global 参照で掴むので、 + * [destroy] で外さないとこのコントローラ(と全オーバーレイ)がプロセスに残る。 + */ + private var touchListener: OpenMobileMapsTouchListener? = null + /** SDK のイベントをコアの受け口へ転送する。 */ fun installListeners() { - holder.map.getTouchHandler().insertListener(OpenMobileMapsTouchListener(this), 0) + val listener = OpenMobileMapsTouchListener(this) + touchListener = listener + holder.map.getTouchHandler().insertListener(listener, 0) holder.map.getCamera().addListener(cameraListener) notifyMapInitialized() } @@ -467,6 +475,8 @@ class OpenMobileMapsMapViewController( override fun destroy() { cancelCameraAnimation() runCatching { holder.map.getCamera().removeListener(cameraListener) } + touchListener?.let { listener -> runCatching { holder.map.getTouchHandler().removeListener(listener) } } + touchListener = null removeDragTouchInterceptor() super.destroy() } From 4cf351c8062c7099b1a54e4c73ac1cdcf98bfe7d Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Sat, 7 Nov 2026 16:20:26 -0800 Subject: [PATCH 3/3] Read the controller through the state base, which MapViewBase clears The state kept its own controller field, set on attach and never cleared, so a state the app keeps held the destroyed controller and every overlay of the old map. It now reads the base's attached controller, which MapViewBase detaches when the map is torn down. --- .../mapconductor/openmobilemaps/OpenMobileMapsMapView.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt index ec26c87..f205baa 100644 --- a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt +++ b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt @@ -64,7 +64,10 @@ class OpenMobileMapsViewState( cameraPosition: MapCameraPosition = MapCameraPosition.Default, ) : MapViewState(cameraPosition), OpenMobileMapsViewStateInterface { - private var controller: OpenMobileMapsMapViewController? = null + // Read through the base so that letting go of the controller there (MapViewBase + // does it when the map is torn down) leaves nothing behind here. + private val controller: OpenMobileMapsMapViewController? + get() = attachedMapController as? OpenMobileMapsMapViewController private var current: OpenMobileMapsMapDesignTypeInterface = mapDesignType override var mapDesignType: OpenMobileMapsMapDesignTypeInterface @@ -75,7 +78,6 @@ class OpenMobileMapsViewState( } internal fun setController(controller: OpenMobileMapsMapViewController) { - this.controller = controller attachController(controller) }