diff --git a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt index f2ae8f9..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) } @@ -280,6 +282,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, ) } 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() }