From 84c52cac6e23c417bb8c4844dc478a8d0e170980 Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Sat, 7 Nov 2026 13:16:50 -0800 Subject: [PATCH 1/3] Destroy the controller when the map leaves the composition MTMapView destroys its WebView, but nothing destroyed MapTilerMapViewController: its tile-server routes, overlay managers and coroutine scope stayed. It is now destroyed with the WebView it belongs to, also when a design change replaces it. --- src/main/java/com/mapconductor/maptiler/MapTilerMapView.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/mapconductor/maptiler/MapTilerMapView.kt b/src/main/java/com/mapconductor/maptiler/MapTilerMapView.kt index 7c54322..9cc683b 100644 --- a/src/main/java/com/mapconductor/maptiler/MapTilerMapView.kt +++ b/src/main/java/com/mapconductor/maptiler/MapTilerMapView.kt @@ -239,6 +239,13 @@ fun MapTilerMapSurface( onDispose { state.serviceRegistry.remove(MarkerRenderingSupportKey) } } + // MTMapView destroys its WebView itself; the controller (tile-server + // routes, overlay managers, its coroutine scope) is ours to free. Keyed + // like the WebView, so a design change frees the one it replaces. + DisposableEffect(controller) { + onDispose { controller.destroy() } + } + // 設定を渡すだけ。**タイル経路に倒すかはコントローラが件数を見て決める** // (`shouldUseMarkerLayer`)。ここで `useMarkerLayer = markerTiling != null` と // 書くと、しきい値未満の件数でもタイル経路に落ちてマーカーが 1 つも描かれない。 From db4ed908ab3d613c74c7aea08942071d5ca8997c Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Sat, 7 Nov 2026 16:20:26 -0800 Subject: [PATCH 2/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. --- .../java/com/mapconductor/maptiler/MapTilerViewStateImpl.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/mapconductor/maptiler/MapTilerViewStateImpl.kt b/src/main/java/com/mapconductor/maptiler/MapTilerViewStateImpl.kt index 3d3b926..07f00a2 100644 --- a/src/main/java/com/mapconductor/maptiler/MapTilerViewStateImpl.kt +++ b/src/main/java/com/mapconductor/maptiler/MapTilerViewStateImpl.kt @@ -38,7 +38,10 @@ class MapTilerViewState( MapTilerViewStateInterface { private var _mapDesignType by mutableStateOf(mapDesignType) - private var controller: MapTilerMapViewController? = 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: MapTilerMapViewController? + get() = attachedMapController as? MapTilerMapViewController override var mapDesignType: MapTilerMapDesignTypeInterface get() = _mapDesignType @@ -49,7 +52,6 @@ class MapTilerViewState( /** MapView 生成時にコントローラを紐付ける。 */ fun setController(controller: MapTilerMapViewController) { - this.controller = controller // 初期カメラは MTMapOptions で地図生成時に渡しているので、接続時には移動しない。 attachController(controller, moveToInitialCamera = false) } From 5cf10d70a2bf9ee6737b204adb256c53c8248ae8 Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Sat, 7 Nov 2026 17:21:31 -0800 Subject: [PATCH 3/3] Detach the controller from the state when the map is disposed This provider does not go through MapViewBase, which does it for the others; a state the app keeps held the destroyed controller and its overlays. Only if it is still the attached one, so a design change keeps the new one. --- .../java/com/mapconductor/maptiler/MapTilerMapView.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/mapconductor/maptiler/MapTilerMapView.kt b/src/main/java/com/mapconductor/maptiler/MapTilerMapView.kt index 9cc683b..556e8fa 100644 --- a/src/main/java/com/mapconductor/maptiler/MapTilerMapView.kt +++ b/src/main/java/com/mapconductor/maptiler/MapTilerMapView.kt @@ -243,7 +243,14 @@ fun MapTilerMapSurface( // routes, overlay managers, its coroutine scope) is ours to free. Keyed // like the WebView, so a design change frees the one it replaces. DisposableEffect(controller) { - onDispose { controller.destroy() } + onDispose { + controller.destroy() + // No MapViewBase here to do it: the state (which the app keeps) must + // not hold on to the destroyed controller and its overlays. Only if + // it is still the attached one -- after a design change the new + // controller is attached before this runs. + state.detachController(controller) + } } // 設定を渡すだけ。**タイル経路に倒すかはコントローラが件数を見て決める**